[javascript] How to show SVG file on React Native?

I want to show svg files (I have bunch of svg images) but the thing I couldn't find the way to show. I tried to use Image and Use components of react-native-svg but they don't work with that. And I tried to do that with native way but it's really hard work to show just svg image.

Example code:

import Svg, {
  Use,
  Image,
} from 'react-native-svg';

<View>
  <Svg width="80" height="80">
     <Image href={require('./svg/1f604.svg')} />
  </SvgRn>
</View>

Also I know the react native doesn't support svg basically but I think someone fixed this problem with tricky way (with/without react-native-svg)

This question is related to javascript svg react-native

The answer is


you can do this using a simple way

first, you should take installation,

  1. npm install -s react-native-svg
  2. react-native link react-native-svg
  3. npm install -s react-native-svg-transformer

then, you should add the following code in your metro.config.js file

_x000D_
_x000D_
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"]
    }
  };
})();
_x000D_
_x000D_
_x000D_

after that, you should create a new file in your root directory with the name of declarations.d.js with the following code

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

Finally, This is a import mathod

_x000D_
_x000D_
import USER from "../../assets/icons/user.svg"
_x000D_
_x000D_
_x000D_

and, this is for jsx

_x000D_
_x000D_
<USER width="100%" height="100%"/>
_x000D_
_x000D_
_x000D_


you can convert any SVG to a component and make it reusable.

here is my answer for the easiest way you can do it

SVG to component


I had the same problem. I'm using this solution I found: React Native display SVG from a file

It's not perfect, and i'm revisiting today, because it performs a lot worse on Android.


Use https://github.com/kristerkari/react-native-svg-transformer

In this package it is mentioned that .svg files are not supported in React Native v0.57 and lower so use .svgx extension for svg files.

For web or react-native-web use https://www.npmjs.com/package/@svgr/webpack


To render svg files using react-native-svg-uri with react-native version 0.57 and lower, you need to add following files to your root project

Note: change extension svg to svgx

step 1: add file transformer.js to project's root

// file: transformer.js

const cleanupSvg = require('./cleanup-svg');

const upstreamTransformer = require("metro/src/transformer");

// const typescriptTransformer = require("react-native-typescript-transformer");
// const typescriptExtensions = ["ts", "tsx"];

const svgExtensions = ["svgx"]

// function cleanUpSvg(text) {
//   text = text.replace(/width="([#0-9]+)px"/gi, "");
//    text = text.replace(/height="([#0-9]+)px"/gi, "");
//    return text;
// }

function fixRenderingBugs(content) {
  // content = cleanUpSvg(content); // cleanupSvg removes width and height attributes from svg
  return "module.exports = `" + content + "`";
}


module.exports.transform = function ({ src, filename, options }) {
  // if (typescriptExtensions.some(ext => filename.endsWith("." + ext))) {
  //  return typescriptTransformer.transform({ src, filename, options })
  // }

  if (svgExtensions.some(ext => filename.endsWith("." + ext))) {
    return upstreamTransformer.transform({
      src: fixRenderingBugs(src),
      filename,
      options
    })
  }

  return upstreamTransformer.transform({ src, filename, options });
}

step 2: add rn-cli.config.js to project's root

module.exports = {
    getTransformModulePath() {
      return require.resolve("./transformer");
    },
    getSourceExts() {
      return [/* "ts", "tsx", */ "svgx"];
    }
  };

The above mentioned solutions will work in production apps too ?


All these solutions are absolutely horrid. Just convert your SVG to a PNG and use the vanilla <Image/> component. The fact that react-native still does not support SVG images in the Image component is a joke. You should never install an additional library for such a simple task. Use https://svgtopng.com/


I posted another solution here Which is the best approach to insert an vector (svg) graph into a react native application, This approach use a vector font(from svg) instead a svg file. PS: Its works great in ios and android, and you also can change the color and size of your vector icon.

If you want to insert a svg directly into your app, you can try a 3rd party library : react-native-svg. With more than 3k stars in github it's one of the best approach.

  • install:
    • npm i react-native-svg
    • npm i react-native-svg-uri
  • link the to native:
    • react-native link react-native-svg

And here's a sample:

import * as React from 'react';
import SvgUri from 'react-native-svg-uri';
import testSvg from './test.svg';
export default () => (
  <SvgUri
    width="200"
    height="200"
    svgXmlData={testSvg}
  />
);

Note: Svg does not work for android release versions so do not consider for android. It will work for android in debug mode only. But it works fine for ios.

Use https://github.com/vault-development/react-native-svg-uri

Install

npm install react-native-svg-uri --save
react-native link react-native-svg # not react-native-svg-uri

Usage

import SvgUri from 'react-native-svg-uri';


<SvgUri source={require('./path_to_image/image.svg')} />

I used the following solution:

  1. Convert .svg image to JSX with https://svg2jsx.herokuapp.com/
  2. Convert the JSX to react-native-svg component with https://svgr.now.sh/ (check the "React Native checkbox)

Install react-native-svg-transformer

npm i react-native-svg-transformer --save-dev

I'm using SVG as following and it works fine

import LOGOSVG from "assets/svg/logo.svg"

in render

<View>
  <LOGOSVG 
    width="100%"
    height="70%"
  />
</View>

I've tried all the above solutions and other solutions outside of the stack and none of working for me. finally, after long research, I've found one solution for my expo project.

If you need it to work in expo, one workaround might be to use https://react-svgr.com/playground/ and move the spreading of props to a G element instead of the SVG root like this:

import * as React from 'react';
import Svg, { G, Path } from 'react-native-svg';

function SvgComponent(props) {
  return (
    <Svg viewBox="0 0 511 511">
      <G {...props}>
        <Path d="M131.5 96c-11.537 0-21.955 8.129-29.336 22.891C95.61 132 92 149.263 92 167.5s3.61 35.5 10.164 48.609C109.545 230.871 119.964 239 131.5 239s21.955-8.129 29.336-22.891C167.39 203 171 185.737 171 167.5s-3.61-35.5-10.164-48.609C153.455 104.129 143.037 96 131.5 96zm15.92 113.401C142.78 218.679 136.978 224 131.5 224s-11.28-5.321-15.919-14.599C110.048 198.334 107 183.453 107 167.5s3.047-30.834 8.581-41.901C120.22 116.321 126.022 111 131.5 111s11.28 5.321 15.919 14.599C152.953 136.666 156 151.547 156 167.5s-3.047 30.834-8.58 41.901z" />
        <Path d="M474.852 158.011c-1.263-40.427-10.58-78.216-26.555-107.262C430.298 18.023 405.865 0 379.5 0h-248c-26.365 0-50.798 18.023-68.797 50.749C45.484 82.057 36 123.52 36 167.5s9.483 85.443 26.703 116.751C80.702 316.977 105.135 335 131.5 335a57.57 57.57 0 005.867-.312 7.51 7.51 0 002.133.312h48a7.5 7.5 0 000-15h-16c10.686-8.524 20.436-20.547 28.797-35.749 4.423-8.041 8.331-16.756 11.703-26.007V503.5a7.501 7.501 0 0011.569 6.3l20.704-13.373 20.716 13.374a7.498 7.498 0 008.134 0l20.729-13.376 20.729 13.376a7.49 7.49 0 004.066 1.198c1.416 0 2.832-.4 4.07-1.2l20.699-13.372 20.726 13.374a7.5 7.5 0 008.133 0l20.732-13.377 20.738 13.377a7.5 7.5 0 008.126.003l20.783-13.385 20.783 13.385a7.5 7.5 0 0011.561-6.305v-344a7.377 7.377 0 00-.146-1.488zM187.154 277.023C171.911 304.737 152.146 320 131.5 320s-40.411-15.263-55.654-42.977C59.824 247.891 51 208.995 51 167.5s8.824-80.391 24.846-109.523C91.09 30.263 110.854 15 131.5 15s40.411 15.263 55.654 42.977C203.176 87.109 212 126.005 212 167.5s-8.824 80.391-24.846 109.523zm259.563 204.171a7.5 7.5 0 00-8.122 0l-20.78 13.383-20.742-13.38a7.5 7.5 0 00-8.131 0l-20.732 13.376-20.729-13.376a7.497 7.497 0 00-8.136.002l-20.699 13.373-20.727-13.375a7.498 7.498 0 00-8.133 0l-20.728 13.375-20.718-13.375a7.499 7.499 0 00-8.137.001L227 489.728V271h8.5a7.5 7.5 0 000-15H227v-96.5c0-.521-.054-1.03-.155-1.521-1.267-40.416-10.577-78.192-26.548-107.231C191.936 35.547 182.186 23.524 171.5 15h208c20.646 0 40.411 15.263 55.654 42.977C451.176 87.109 460 126.005 460 167.5V256h-.5a7.5 7.5 0 000 15h.5v218.749l-13.283-8.555z" />
        <Path d="M283.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15zM331.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15zM379.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15zM427.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15z" />
      </G>
    </Svg>
  );
}

export default function App() {
  return (
    <SvgComponent width="100%" height="100%" strokeWidth={5} stroke="black" />
  );
}

import React from 'react'
import SvgUri from 'react-native-svg-uri';

export default function Splash() {
  return (
    <View style={styles.container}>
      {/* provided the svg file is stored locally */}
      <SvgUri
        width="400"
        height="200"
        source={require('./logo.svg')}
      />
      {/* if the svg is online */}
      <SvgUri
        width="200"
        height="200"
        source={{ uri: 'http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg' }}
      />

      <Text style={styles.logoText}>
        Text
      </Text>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  logoText: {
    fontSize: 50
  }
});

I use these two plugins,

  1. [react-native-svg] https://github.com/react-native-community/react-native-svg)
  2. [ react-native-svg-transformer] https://github.com/kristerkari/react-native-svg-transformer)

First off all, You need to install that plugin. After that you need to change your metro.config.js, with this code.

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"]
    }
  };
})();

For more details, you can visit this link


After trying many ways and libraries I decided to create a new font (with Glyphs or this tutorial) and add my SVG files to it, then use "Text" component with my custom font.

Hope this helps anyone that has the same problem with SVG in react-native.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to svg

How to extract svg as file from web page How to display svg icons(.svg files) in UI using React Component? Why don’t my SVG images scale using the CSS "width" property? How to show SVG file on React Native? Easiest way to use SVG in Android? IE11 meta element Breaks SVG img src SVG changing the styles with CSS How to use SVG markers in Google Maps API v3 Embedding SVG into ReactJS How to change the color of an svg element?

Examples related to react-native

How to resolve the error on 'react-native start' React Native Error: ENOSPC: System limit for number of file watchers reached How to update core-js to core-js@3 dependency? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65 How can I force component to re-render with hooks in React? What is useState() in React? Getting all documents from one collection in Firestore ReactJS: Maximum update depth exceeded error React Native: JAVA_HOME is not set and no 'java' command could be found in your PATH