DEV Community

Steve
Steve

Posted on • Originally published at dev.cavender.io on

React-Native SVG Example

Series Intro

Welcome to the first post of my React Native series! Each article in the series will dive into a different aspect of the framework. Let’s go!

Getting Started

To begin we’ll need a React Native application to add SVGs to. I started a new one in my examples repo under svg with the npx react-native init PROJECTNAME command. An existing app will work as well but we’ll have to check version compatibility. Our next step is to fire up the app. I run npm run start which just calls react-native start. Now metro is running in this terminal and we need to open a new terminal. In the new terminal let’s fire up the app in either iOS or Android. I started with Android so I ran npm run android which just runs react-native run-android. Now we have an Android emulator running our app! Here’s a screenshot of where we’re at on Android:

Initial Screen

Drawing SVGs

React Native doesn’t support SVG out of the box. So we’ll have to install a package to handle SVGs for us. I chose svg-react-native. Here’s where we need to pay attention to the versions we’re on. There are various steps to getting this package to work in the app depending on the versions it has. Be sure to read through the Readme and the table of versions. Since I’m on a brand new app I ran npm i react-native-svg to install the latest. Now with the package installed we can import it and start drawing SVGs in our app! I added a separate component to contain my SVG: /components/svg.js. Here’s my component code:

import React from 'react';
import type {Node} from 'react';
import Svg, {Circle, Rect, Path} from 'react-native-svg';
import {View} from 'react-native';

const SvgComp = (): Node => {
  return (
    <View>
      <Svg height="100" width="100">
        <Rect x="0" y="0" width="100" height="100" fill="black" />
        <Circle cx="50" cy="50" r="30" fill="yellow" />
        <Circle cx="40" cy="40" r="4" fill="black" />
        <Circle cx="60" cy="40" r="4" fill="black" />
        <Path d="M 40 60 A 10 10 0 0 0 60 60" stroke="black" />
      </Svg>
    </View>
  );
};

export default SvgComp;

Enter fullscreen mode Exit fullscreen mode

And here’s a screenshot of how it renders in the Android emulator:

SVG Drawing


NOTE

I had to restart metro and re-run the android command to get SVGs working.


Check out the supported elements to see what else we can do with SVGs now.

Using an SVG Font

Being able to draw our own SVGs is cool but let’s pull in an SVG font with a bunch of icons we can use. I chose a set of open source icons called Feather. Yiğithan has already done the work for those of us that want to use Feather icon SVGs in our React Native apps with react-native-feather. Install the package with npm i react-native-feather and pop in any of the Feather icons. I created another separate component to try out Feather icons in my example app: /components/feather.js. Here’s my component code:

import React from 'react';
import type {Node} from 'react';
import {View} from 'react-native';
import {ArrowUpCircle} from 'react-native-feather';

const FeatherComp = (): Node => {
  return (
    <View>
      <ArrowUpCircle stroke="red" fill="#fff" width={32} height={32} />
    </View>
  );
};

export default FeatherComp;

Enter fullscreen mode Exit fullscreen mode

And here’s a screenshot of how it renders in the Android emulator:

Feather Icon

This is great because now we have access to all of the Feather icons as React components. But what if we had an SVG file we wanted to use?

Using SVG Files

Maybe we have some SVG files we want to include rather than including a font of them. For this case we’ll need another package. Kristerkari has us covered with react-native-svg-transformer. Install the package with npm i --save-dev react-native-svg-transformer. Next we’ll update our metro config to handle transforming SVGs. Here’s what my metro.config.js looks like now:

const {getDefaultConfig} = require('metro-config');

module.exports = (async () => {
  const {
    resolver: {sourceExts, assetExts},
  } = await getDefaultConfig();
  return {
    transformer: {
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: true,
        },
      }),
      babelTransformerPath: require.resolve('react-native-svg-transformer'),
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg'],
    },
  };
})();

Enter fullscreen mode Exit fullscreen mode

I needed some SVG files so I grabbed these:

And another new component for SVG files: ./components/svg-files.js. Here’s the component code:

import React from 'react';
import type {Node} from 'react';
import {View} from 'react-native';
import Coffee from '../assets/icons/coffee.svg';
import Firefox from '../assets/icons/firefox.svg';

const SvgFilesComp = (): Node => {
  return (
    <View>
      <Firefox />
      <Coffee />
    </View>
  );
};

export default SvgFilesComp;

Enter fullscreen mode Exit fullscreen mode

And here’s a screenshot of how it renders in the Android emulator:

SVG File Initial Screen


NOTE

I had to restart metro and re-run the android command to get SVGs working.


Notice that our coffee SVG isn’t visible but taking space. That’s because its designed to be customizable. We need to pass in some arguments if we want it to render in color. Which arguments and whether it’s customizable at all depends on the SVG.

For instance, both SVGs I chose have widths and heights set for them. If we don’t include those properties then their defaults are used. If we pass in a width to the firefox SVG check out what happens:

<Firefox width={50} />
<Coffee />

Enter fullscreen mode Exit fullscreen mode

SVG File Firefox Width

The image is the correct size but the overall SVG is still taking up a lot more room than it needs. We have to pass in both sizes to fix this. While we’re at it, let’s give some color to our coffee icon by passing in a fill color.

<Firefox width={50} height={50} />
<Coffee fill={'blue'} />

Enter fullscreen mode Exit fullscreen mode

SVG File Firefox Size Coffee Fill

Now our firefox looks good but our coffee icon does not. This particular icon isn’t meant to have a fill. Rather, we should pass in a stroke to get the desired look.

<Firefox width={50} height={50} />
<Coffee stroke={'#333'} />

Enter fullscreen mode Exit fullscreen mode

SVG File Final

Now those are some good looking SVGs in a React Native app!

Conclusion

In this article we covered how to include SVGs inside a React Native application using three different methods:

  1. Drawing them
  2. Importing an SVG font
  3. Loading from .svg files

Thanks for reading! Please share using any of the buttons below and stay tuned for more of my React Native series of posts. Don’t hesitate to reach out in the comments below or on any of the links in the author profile.

Top comments (1)

Collapse
 
marcosantonioreyesmedina profile image
Marcos Antonio Reyes Medina • Edited

Is it possible to use an SVG sprite like the one used on the web?
Something like this:

<Svg width={64} height={64}>
   <Use href={`${Sprite}#${iconId}`} />
</Svg>
Enter fullscreen mode Exit fullscreen mode