Nov 24, 2022 5 min read Updating SVG image color dynamically in React-Native

What is SVG and usage of SVG icon:

Scalable Vector Graphics (SVG) is an XML based language for describing two-dimensional vector graphics.

Usage of SVG: -

  • SVG images can be rendered in any size without losing any quality.
  • File size: - SVG image has a small file size that compresses well.
  • Style control: - You can change the styles within your SVG image.

Getting started with React Native:

If you are a beginner in React-Native go with Expo-CLI. npm install -g expo-cli expo init SvgTransformer cd SvgTransformer expo start // you can also use: npm start

How to use SVG file in React Native:

React Native doesn’t support SVG by default, to use SVGs in react native project you need to transform those images into React components by SVGR to display the components. This can be done by using react-native-svg package.

Getting started with react-native-svg:

Install react-native-svg library

If you use React Native version older than 0.60, you need to link react-native-svg manually

Get start with react-native-svg-transformer:

yarn add --dev react-native-svg-transformer || npm install -d react-native-svg-transformer

For Expo SDK v40.0.0 or newerMerge the contents from your project’s metro.config.js file with this config (create the file if it does not exist already)

metro.config.js:

const { getDefaultConfig } = require("@expo/metro-config");
module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig(__dirname);
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"]
    }
  };
})();

For React Native v0.57 or newer / Expo SDK v31.0.0 or newer, if you are using Expo, merge the contents from your project’s metro.config.js file with this config (create the file if it does not exist already).

metro.config.js:

const { getDefaultConfig } = require("metro-config");
module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"]
    }
  };
})();

If you are using Expo, you also need to add this to app.json:

{
  "expo": {
    "packagerOpts": {
      "config": "metro.config.js",
      "sourceExts": [
        "expo.ts",
        "expo.tsx",
        "expo.js",
        "expo.jsx",
        "ts",
        "tsx",
        "js",
        "jsx",
        "json",
        "wasm",
        "svg"
      ]
    }
  }
}

Check here For React Native v0.56 or older / For Expo SDK v30.0.0 or older

Using TypeScript:

If you are using TypeScript, you need to add this to your declarations.d.ts file (create one if you don’t have one already):

import React from 'react';
declare module "*.svg" {
  import { SvgProps } from "react-native-svg";
  const content: React.FC<SvgProps>;
  export default content;
}

let us Make our hands dirty:

Step-1:-

Download and add an SVG file into your asset folder and import that into your project file. Click the here to download one.

After the downloading SVG image into your project, select your SVG image and change the fill to currentColor (For some SVG it will be stroke)

It will be available on the end of the path tag.

Step 2:-

After the downloading SVG image into your project, select your SVG image and change the fill to currentColor (For some SVG it will be stroke)

Initialize 3 states for 3 icons to change the color of the SVG image, for that we can use the useState hook from React. Here initial state will be false.

const [isBlue, setIsBlue] = React.useState(false);
const [isRed, setIsRed] = React.useState(false);
const [isViolet, setIsViolet] = React.useState(false);

Step 3:-

Add a touchable effect using TouchableOpacity inside a parent View and add SVG Image inside the TouchableOpacity

TouchableOpacity is a wrapper for making views respond properly to touches. On press down, the opacity of the wrapped view is decreased, dimming it.

<View style={Styles.container}>
      <TouchableOpacity style={Styles.button}>
          <WhatsAppIcon 
        height={50}
         width={50} 
           />
      </TouchableOpacity>
     ...
 </View>

Step 4:-

Now we need to change the color of the SVG Image, for that we can change the state to the opposite of the initial state.

onPress={() =>  setIsBlue(!isBlue)}

Here we changed the state to the opposite of the current state. Now we need to change the color of the SVG Image by checking the state of the SVG image here initial color is "#4FCE5D" (moderate lime green) whenever the user tap on that image the state changes and the corresponding color will be shown.

style ={{ color: isBlue ? "#0000FF" : "#4FCE5D" }}

Step 5:-

Repeat these steps for the remaining 2 images for that wrap your SVG image inside the TouchableOpacity and repeat the steps above mentioned.

Let’s see the final result: VID-20210501-WA0007.gif Here is the GitHub Link and for more reference react-native-svg-transformer.

Here is the full code:
import React from "react";
import { View, Text, StyleSheet } from "react-native";
import WhatsAppIcon from "../../assets/svg/whatsapp_icon.svg";
import { TouchableOpacity } from "react-native-gesture-handler";
const MainScreen = () => {
  const [isBlue, setIsBlue] = React.useState(false);
  const [isRed, setIsRed] = React.useState(false);
  const [isViolet, setIsViolet] = React.useState(false);
return (
    <View style={Styles.container}>
      <TouchableOpacity style={Styles.button}>
        <WhatsAppIcon
          style={[
            isBlue
              ? { color: "#0000FF" }
              : { color: "#4FCE5D" },
          ]}
          height={50}
          width={50}
          onPress={() => {
            setIsBlue(!isBlue);
          }}
        />
      </TouchableOpacity>
      <TouchableOpacity style={Styles.button}>
        <WhatsAppIcon
          style={[
            isRed
              ? {color: "#FF0000" }
              : { color: "#4FCE5D" },
          ]}
          height={50}
          width={50}
          onPress={() => {
            setIsRed(!isRed);
          }}
        />
      </TouchableOpacity>
      <TouchableOpacity style={Styles.button}>
        <WhatsAppIcon
          style={[
            isViolet
              ? { color: "#DA70D6" }
              : { color: "#4FCE5D" },
          ]}
          height={50}
          width={50}
          onPress={() => {
            setIsViolet(!isViolet);
          }}
        />
      </TouchableOpacity>
    </View>
  );
};
export default MainScreen;
const Styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "row",
    justifyContent: "space-around",
    alignItems: "center",
  },
  button: {
    flex: 1,
    height: "100%",
    width: "100%",
    alignItems: "center",
    justifyContent: "center",
  },
});

Author(s)

Topics

Share this blog

5 min read

Nov 24, 2022

This website stores cookies on your computer.

These cookies are used to collect information about how you interact with this website and allow us to remember you. We use this information in order to improve and customize your browsing experience and for analytics and metrics about our visitors on this website.

If you decline, your information won’t be tracked when you visit this website. A single cookie will be used in your browser to remember your preference not to be tracked.