DEV Community

Brianna Workman
Brianna Workman

Posted on

How to use SVGs in React Native with Expo

SVG is a vector format that can scale to any size without losing its quality, and this is what makes them highly desirable in the development of mobile apps. However, React Native hasn’t exactly ironed out all the kinks for the use of SVGs as of yet.

At the time this post is written, there are many ways to try to use SVG images in your project. The most common and stable one being the use of react-native-svg-uri. It allows you to render SVG images in React Native from a URL or a static file using the SvgUri component.

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

const TestSvgUri = () => (
  <View style={styles.container}>
    <SvgUri
      width="200"
      height="200"
      source={{uri:'http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg'}}
    />
  </View>
);

While this is a fantastic and simple library to use, it comes with one major bug: on Android, everything seems to work okay in development but fails to load the file in release mode. Meaning your SVGs show up when you’re testing your app in development or debug mode, but the second you push to the Google Play store, your SVGs are no longer rendered on Android devices.

As of right now, the only known workaround is to pass the SVG content in the svgXmlData prop. But, this prop can only be accessed when you link to react-native-svg using the following command:

react-native link react-native-svg

Now, if you aren’t using Expo, you can probably stop here and have success linking to react-native-svg and using the SvgUri component and svgXmlData prop. But if you are using Expo, this is where it comes into play.

The most limiting thing about Expo is that you can’t add in your own native modules without detaching. So, if you want to use anything that requires react-native link, like what is required above, then you need to detach your project and develop it with or without ExpoKit. A solution? Sure, as long as you don’t mind losing certain features and integrations (such as Expo’s push notifications service) when doing so, but that is the trade-off Expo provides as an all-in-one package. When detaching, you lose those features.

So, how do we implement SVGs in our React Native projects without losing all of the added features and integrations Expo gives us?

Well, there is a way to run Expo and raw React Native together, and if you’re interested in learning more about that, you can check out this article here.

Otherwise, you can follow along as I show you how to quickly add iOS and Android supported SVGs to your Expo app.

I. Create a New Expo App

expo init my-expo-app

Choose a bare app JavaScript template and open it in your favorite editor.

II. Add react-native-svg

expo install react-native-svg

III. Add Your SVG File to the assets Folder

IV. Add a folder in the root of your project

I’m going to call mine svgs, but you can name this whatever you want

V. Add a .js file in the folder we made in step 4

I’m calling mine SvgTest.js, but again, you can name this whatever you want

VI. Import the proper components and create your function

import React from "react";
import { SvgXml } from "react-native-svg";

export default function SvgTest(){
    return()
}

VII. Go into your .svg file and copy everything in there

VIII. Create a constant in your .js file and paste your SVG contents inside a pair of backticks

const smile = `<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="smile" class="svg-inline--fa fa-smile fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="black" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"></path></svg>`;

IX. Create a function in your .js file and use the SvgXml component from react-native-svg

Here you are going to pass your previous constant into the xml prop. You can also define your height and width.

const SmileSvg = () => <SvgXml xml={smile} width='50%' height='50%' />;

X. Return your function

Your completed .js file should look like this

import React from 'react';
import { SvgXml } from 'react-native-svg';

export default function SvgTest() {
  const smile = `<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="smile" class="svg-inline--fa fa-smile fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="black" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"></path></svg>`;

  const SmileSvg = () => <SvgXml xml={smile} width='50%' height='50%' />;

  return <SmileSvg />;
}

XI. Import your new SVG component into your App.js and use it as you would a normal React Native component

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import SvgTest from './svgs/SvgTest';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <SvgTest />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  }
});

XII. Run your project and start your simulator

expo start

SVG displayed on iPhone 11 Pro Max

Top comments (0)