How can I 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>

i know react native doesn’t support svg basically but i think someone fix this problem with tricky way (with/without react-native-svg)

Also i created the topic on stack overflow.
http://stackoverflow.com/questions/38830568/how-can-i-show-svg-file-on-react-native

19 thoughts on “How can I show SVG file on React Native?

  1. @richardgill i can help for 2nd question 😄

    If you add the images (or svgs) to Images.xcassets (on xcode) or drawable folder (on android), you can access to images that you want easily.

  2. The idea is just to break down your svg into its individual paths and then each path would be a property within the json object.

    {
    "path":"M41.55-23.70Q41.55-18.18 40.17-13.62Q38.78-9.07 36.16-5.78Q33.54-2.50 29.97-0.77Q26.40 0.95 22.04 0.95Q16.10 0.95 11.76-2.34Q7.42-5.63 5.12-11.25Q2.81-16.88 2.81-23.48Q2.81-29.95 5.22-35.67Q7.63-41.38 12.20-44.84Q16.77-48.30 22.68-48.30Q28.13-48.30 32.43-45.32Q36.74-42.33 39.15-36.70Q41.55-31.08 41.55-23.70M22.04-2.53Q26.05-2.53 28.65-5.77Q31.25-9 32.43-14.26Q33.61-19.51 33.61-25.49Q33.61-29.88 32.92-33.43Q32.24-36.98 30.90-39.52Q29.57-42.05 27.54-43.45Q25.52-44.86 22.89-44.86Q19.27-44.86 16.79-42.56Q14.31-40.25 12.99-36.63Q11.67-33.01 11.20-29.30Q10.72-25.59 10.72-22.11Q10.72-17.75 11.71-13.31Q12.69-8.86 15.22-5.70Q17.75-2.53 22.04-2.53Z"
    }
    

    Then you can simply import the json into your app and use react-native-svg to render the svg like this:

      const json = require('./svg.json');
    
      render() {
        return (
          <Svg height={200} width={200} >
            <Path d={json['path']} />
          </Svg>
        );
      }
    
  3. Watch out if you target Android, from the README for react-native-svg-uri:

    [ANDROID] There is a problem with static SVG file on Android, Works OK in debug mode but fails to load the file in release mode. At the moment the only workaround is to pass the svg content in the svgXmlData prop.

    What I do is I use svg-to-react-cli and then tweak the output, saves some time, but it’s still not optimal.

  4. Release mode in android requires a bit of extra work:
    App.js

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

    .babelrc

    {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [
        ["babel-plugin-inline-import", {
          "extensions": [
            ".svg"
          ]
        }]
      ]
    }
    

    @matc4 Perhaps should update the documentation?

  5. Release mode in android requires a bit of extra work:
    App.js

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

    .babelrc

    {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [
        ["babel-plugin-inline-import", {
          "extensions": [
            ".svg"
          ]
        }]
      ]
    }

    @matc4 Perhaps should update the documentation?

    it’s not working well with mine now.

    • As getting this issue for now

    This is IOS Simulator screen

    This is How I implement your solution

    import imgSrc from '../../assets/images/background.svg';
    
    <SvgUri
          svgXmlData={imgSrc}
        />
    

    This is How I create .babelrc file like you make

    {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [
        ["babel-plugin-inline-import", {
          "extensions": [
            ".svg"
          ]
        }]
      ]
    }
    

    Updated

    • Installed metro-react-native-babel-preset already.

    Let’s advise

  6. @lunvjp i have the same problem, and i figure it out, the config in metro.config.js has an item called inlineRequires, it is false, set it to true and done.

    module.exports = {
      transformer: {
        getTransformOptions: async () => ({
          transform: {
            experimentalImportSupport: false,
            inlineRequires: true,
          },
        }),
      },
    };
    
  7. Docs have been updated, react-native-svg includes this functionality now: Use with content loaded from uri

    import * as React from 'react';
    import { SvgUri } from 'react-native-svg';
    
    export default () => (
      <SvgUri
        width="100%%"
        height="100%%"
        uri="http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg"
      />
    );

    Use with xml strings

    import * as React from 'react';
    import { SvgXml } from 'react-native-svg';
    
    const xml = `
      <svg width="32" height="32" viewBox="0 0 32 32">
        <path
          fill-rule="evenodd"
          clip-rule="evenodd"
          fill="url(#gradient)"
          d="M4 0C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H28C30.2091 32 32 30.2091 32 28V4C32 1.79086 30.2091 0 28 0H4ZM17 6C17 5.44772 17.4477 5 18 5H20C20.5523 5 21 5.44772 21 6V25C21 25.5523 20.5523 26 20 26H18C17.4477 26 17 25.5523 17 25V6ZM12 11C11.4477 11 11 11.4477 11 12V25C11 25.5523 11.4477 26 12 26H14C14.5523 26 15 25.5523 15 25V12C15 11.4477 14.5523 11 14 11H12ZM6 18C5.44772 18 5 18.4477 5 19V25C5 25.5523 5.44772 26 6 26H8C8.55228 26 9 25.5523 9 25V19C9 18.4477 8.55228 18 8 18H6ZM24 14C23.4477 14 23 14.4477 23 15V25C23 25.5523 23.4477 26 24 26H26C26.5523 26 27 25.5523 27 25V15C27 14.4477 26.5523 14 26 14H24Z"
        />
        <defs>
          <linearGradient
            id="gradient"
            x1="0"
            y1="0"
            x2="8.46631"
            y2="37.3364"
            gradient-units="userSpaceOnUse">
            <stop offset="0" stop-color="#FEA267" />
            <stop offset="1" stop-color="#E75A4C" />
          </linearGradient>
        </defs>
      </svg>
    `;
    
    export default () => <SvgXml xml={xml} width="100%%" height="100%%" />;

    Also, released today in v9.13.0, SvgCss and SvgCssUri, same as SvgXml and SvgUri but with support for css style elements, with handling of the cascade, media queries, pseudo selectors, specificities, priorities, complex selectors etc:

    import React from 'react';
    import {SvgCss} from 'react-native-svg';
    
    const xml = `<svg xmlns="http://www.w3.org/2000/svg"
      width="100%%"
      height="100%%"
      viewBox="0 0 1000 500"
    >
      <defs>
        <style type="text/css">
          rect {
            fill: lightgreen;
            stroke: blue;
            stroke-width: 5;
          }
        </style>
      </defs>
      <rect x="200" y="100" width="600" height="300" />
    </svg>
    `;
    
    const App = () => <SvgCss xml={xml} />;
    
    export default App;

    https://github.com/react-native-community/react-native-svg/blob/8c1a1737b052000569662d6f2539ffe3c47564ba/__tests__/css.test.tsx#L1-L54

  8. import {SvgCss} from 'react-native-svg';
    
    const xml = (obj) =>
      `<svg
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
        fill="none"
        stroke="${obj.color}"
        stroke-width="2"
        stroke-linecap="round"
        stroke-linejoin="round"
        class="feather feather-film">
        <rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"></rect>
        <line x1="7" y1="2" x2="7" y2="22"></line>
        <line x1="17" y1="2" x2="17" y2="22"></line>
        <line x1="2" y1="12" x2="22" y2="12"></line>
        <line x1="2" y1="7" x2="7" y2="7"></line>
        <line x1="2" y1="17" x2="7" y2="17"></line>
        <line x1="17" y1="17" x2="22" y2="17"></line>
        <line x1="17" y1="7" x2="22" y2="7"></line>
      </svg>
    `
    const App = () => {
        <SvgCss
             xml={xml( {color: 'tomato'} )}
         />
    }
    
                      

Comments are closed.

How can I 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>

i know react native doesn’t support svg basically but i think someone fix this problem with tricky way (with/without react-native-svg)

Also i created the topic on stack overflow.
http://stackoverflow.com/questions/38830568/how-can-i-show-svg-file-on-react-native

12 thoughts on “How can I show SVG file on React Native?

  1. @richardgill i can help for 2nd question 😄

    If you add the images (or svgs) to Images.xcassets (on xcode) or drawable folder (on android), you can access to images that you want easily.

  2. The idea is just to break down your svg into its individual paths and then each path would be a property within the json object.

    {
    "path":"M41.55-23.70Q41.55-18.18 40.17-13.62Q38.78-9.07 36.16-5.78Q33.54-2.50 29.97-0.77Q26.40 0.95 22.04 0.95Q16.10 0.95 11.76-2.34Q7.42-5.63 5.12-11.25Q2.81-16.88 2.81-23.48Q2.81-29.95 5.22-35.67Q7.63-41.38 12.20-44.84Q16.77-48.30 22.68-48.30Q28.13-48.30 32.43-45.32Q36.74-42.33 39.15-36.70Q41.55-31.08 41.55-23.70M22.04-2.53Q26.05-2.53 28.65-5.77Q31.25-9 32.43-14.26Q33.61-19.51 33.61-25.49Q33.61-29.88 32.92-33.43Q32.24-36.98 30.90-39.52Q29.57-42.05 27.54-43.45Q25.52-44.86 22.89-44.86Q19.27-44.86 16.79-42.56Q14.31-40.25 12.99-36.63Q11.67-33.01 11.20-29.30Q10.72-25.59 10.72-22.11Q10.72-17.75 11.71-13.31Q12.69-8.86 15.22-5.70Q17.75-2.53 22.04-2.53Z"
    }
    

    Then you can simply import the json into your app and use react-native-svg to render the svg like this:

      const json = require('./svg.json');
    
      render() {
        return (
          <Svg height={200} width={200} >
            <Path d={json['path']} />
          </Svg>
        );
      }
    
  3. Watch out if you target Android, from the README for react-native-svg-uri:

    [ANDROID] There is a problem with static SVG file on Android, Works OK in debug mode but fails to load the file in release mode. At the moment the only workaround is to pass the svg content in the svgXmlData prop.

    What I do is I use svg-to-react-cli and then tweak the output, saves some time, but it’s still not optimal.

  4. @i-schuetz Doesn’t react-native-svg-uri work?

    import * as React from 'react';
    import SvgUri from 'react-native-svg-uri';
    
    export default () => (
      <SvgUri
        width="200"
        height="200"
        source={{
          uri: 'http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg',
        }}
      />
    );
    

    screen shot 2019-01-23 at 19 29 23

  5. Release mode in android requires a bit of extra work:
    App.js

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

    .babelrc

    {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [
        ["babel-plugin-inline-import", {
          "extensions": [
            ".svg"
          ]
        }]
      ]
    }
    

    @matc4 Perhaps should update the documentation?

  6. Release mode in android requires a bit of extra work:
    App.js

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

    .babelrc

    {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [
        ["babel-plugin-inline-import", {
          "extensions": [
            ".svg"
          ]
        }]
      ]
    }

    @matc4 Perhaps should update the documentation?

    it’s not working well with mine now.

    • As getting this issue for now

    This is IOS Simulator screen

    This is How I implement your solution

    import imgSrc from '../../assets/images/background.svg';
    
    <SvgUri
          svgXmlData={imgSrc}
        />
    

    This is How I create .babelrc file like you make

    {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [
        ["babel-plugin-inline-import", {
          "extensions": [
            ".svg"
          ]
        }]
      ]
    }
    

    Updated

    • Installed metro-react-native-babel-preset already.

    Let’s advise

  7. @lunvjp i have the same problem, and i figure it out, the config in metro.config.js has an item called inlineRequires, it is false, set it to true and done.

    module.exports = {
      transformer: {
        getTransformOptions: async () => ({
          transform: {
            experimentalImportSupport: false,
            inlineRequires: true,
          },
        }),
      },
    };
    
  8. Docs have been updated, react-native-svg includes this functionality now: Use with content loaded from uri

    import * as React from 'react';
    import { SvgUri } from 'react-native-svg';
    
    export default () => (
      <SvgUri
        width="100%%"
        height="100%%"
        uri="http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg"
      />
    );

    Use with xml strings

    import * as React from 'react';
    import { SvgXml } from 'react-native-svg';
    
    const xml = `
      <svg width="32" height="32" viewBox="0 0 32 32">
        <path
          fill-rule="evenodd"
          clip-rule="evenodd"
          fill="url(#gradient)"
          d="M4 0C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H28C30.2091 32 32 30.2091 32 28V4C32 1.79086 30.2091 0 28 0H4ZM17 6C17 5.44772 17.4477 5 18 5H20C20.5523 5 21 5.44772 21 6V25C21 25.5523 20.5523 26 20 26H18C17.4477 26 17 25.5523 17 25V6ZM12 11C11.4477 11 11 11.4477 11 12V25C11 25.5523 11.4477 26 12 26H14C14.5523 26 15 25.5523 15 25V12C15 11.4477 14.5523 11 14 11H12ZM6 18C5.44772 18 5 18.4477 5 19V25C5 25.5523 5.44772 26 6 26H8C8.55228 26 9 25.5523 9 25V19C9 18.4477 8.55228 18 8 18H6ZM24 14C23.4477 14 23 14.4477 23 15V25C23 25.5523 23.4477 26 24 26H26C26.5523 26 27 25.5523 27 25V15C27 14.4477 26.5523 14 26 14H24Z"
        />
        <defs>
          <linearGradient
            id="gradient"
            x1="0"
            y1="0"
            x2="8.46631"
            y2="37.3364"
            gradient-units="userSpaceOnUse">
            <stop offset="0" stop-color="#FEA267" />
            <stop offset="1" stop-color="#E75A4C" />
          </linearGradient>
        </defs>
      </svg>
    `;
    
    export default () => <SvgXml xml={xml} width="100%%" height="100%%" />;

    Also, released today in v9.13.0, SvgCss and SvgCssUri, same as SvgXml and SvgUri but with support for css style elements, with handling of the cascade, media queries, pseudo selectors, specificities, priorities, complex selectors etc:

    import React from 'react';
    import {SvgCss} from 'react-native-svg';
    
    const xml = `<svg xmlns="http://www.w3.org/2000/svg"
      width="100%%"
      height="100%%"
      viewBox="0 0 1000 500"
    >
      <defs>
        <style type="text/css">
          rect {
            fill: lightgreen;
            stroke: blue;
            stroke-width: 5;
          }
        </style>
      </defs>
      <rect x="200" y="100" width="600" height="300" />
    </svg>
    `;
    
    const App = () => <SvgCss xml={xml} />;
    
    export default App;
    import React from react;
    import renderer from react-test-renderer;
    import { SvgCss, parse, inlineStyles } from ../src/ReactNativeSVG;
    const xml = `<?xml version=”1.0″ standalone=”no”?>
    <!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN”
    “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>
    <svg xmlns=”http://www.w3.org/2000/svg” version=”1.1″
    width=”100%%” height=”100%%” viewBox=”0 0 1000 500″>
    <defs>
    <style type=”text/css”>
    /* tag selector */
    rect {
    stroke: blue;
    fill: yellow
    }
    /* class selector */
    .redbox { fill: red; }
    /* multiple selectors */
    g .class-1, g .class-2 {
    stroke-width: 16
    }
    /* two classes */
    .class-2.transparent {
    fill-opacity: 0.3;
    }
    /* Commented out
    rect {
    fill: black;
    }
    */
    </style>
    </defs>
    <g>
    <rect class=”redbox class-1″ x=”100″ y=”0″ width=”1000″ height=”200″ />
    </g>
    <g>
    <rect class=”redbox class-2 transparent” x=”100″ y=”350″ width=”750″ height=”200″ />
    </g>
    </svg>`;
    test(inlines styles, () => {
    const ast = parse(xml, inlineStyles);
    expect(ast).toMatchSnapshot();
    });
    test(supports CSS in style element, () => {
    const tree = renderer.create(<SvgCss xml={xml} />).toJSON();
    expect(tree).toMatchSnapshot();
    });

Comments are closed.