How to display svg icons(.svg files) in UI using React Component?

ReactjsSvg

Reactjs Problem Overview


I have seen a lot of libraries for svg on react but none gave me how to import an svg file in the react component. I have seen code which talk about bring the svg code into react rather than using the .svg icon as image and show it in the UI.

Please let me know if there are ways to embed the icon.

Reactjs Solutions


Solution 1 - Reactjs

If you use create-react-app 2.0 you can now do it like this:

import { ReactComponent as YourSvg } from './your-svg.svg';

And then use it just like you would normally use a component:

const App = () => (
 <div>
   <YourSvg />
 </div>
);

Solution 2 - Reactjs

There are two ways I want to show you.

The first one is just a simple import of the required SVG.

import MyImageSvg from '../../path/to.svg';

Just remember to use a loader for e.g. Webpack:

 {
     test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
     include: [Path.join(__dirname, "src/assets")],
     loader: "file-loader?name=assets/[name].[ext]"
 }

Another (and more elegant way) is that you can define an SVG icon sprite and use a component to fetch the correct sprite of the SVG. For example:

import React from "react";
import Icons from "../../assets/icons/icons.svg"; // Path to your icons.svg
import PropTypes from 'prop-types';

const Icon = ({ name, color, size }) => (
  <svg className={`icon icon-${name}`} fill={color} width={size} height={size}>
    <use xlinkHref={`${Icons}#icon-${name}`} />
  </svg>
);

Icon.propTypes = {
  name: PropTypes.string.isRequired,
  color: PropTypes.string,
  size: PropTypes.number
};

export default Icon;

The icon sprite (icons.svg) can be defined as:

<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  
    <symbol id="icon-account-group" viewBox="0 0 512 512">
      <path d="m256 301l0-41c7-7 19-24 21-60 10-5 16-16 16-30 0-12-4-22-12-28 7-13 18-37 12-60-7-28-48-39-81-39-29 0-65 8-77 30-12-1-20 2-26 9-15 16-8 46-4 62 1 2 2 4 2 5l0 42c0 41 24 63 42 71l0 39c-8 3-17 7-26 10-56 20-104 37-112 64-11 31-11 102-11 105 0 6 5 11 11 11l384 0c6 0 10-5 10-11 0-3 0-74-10-105-11-31-69-48-139-74z m-235 168c1-20 3-66 10-88 5-16 57-35 99-50 12-4 23-8 34-12 4-2 7-6 7-10l0-54c0-4-3-9-8-10-1 0-35-12-35-54l0-42c0-3-1-5-2-11-2-8-9-34-2-41 3-4 11-3 15-2 6 1 11-2 13-8 3-13 29-22 60-22 31 0 57 9 60 22 5 17-6 37-11 48-3 6-5 10-5 14 0 5 5 10 11 10 3 0 5 6 5 11 0 4-2 11-5 11-6 0-11 4-11 10 0 43-16 55-16 55-3 2-5 6-5 9l0 54c0 4 2 8 7 10 51 19 125 41 132 62 8 22 9 68 10 88l-363 0z m480-94c-8-25-49-51-138-84l0-20c7-7 19-25 21-61 4-2 7-5 10-9 4-5 6-13 6-20 0-13-5-23-13-28 7-15 19-41 13-64-4-15-21-31-40-39-19-7-38-6-54 5-5 3-6 10-3 15 3 4 10 6 15 3 12-9 25-6 34-3 15 6 25 18 27 24 4 17-6 40-12 52-3 6-4 10-4 13 0 3 1 6 3 8 2 2 4 3 7 3 4 0 6 6 6 11 0 3-1 6-3 8-1 2-2 2-3 2-6 0-10 5-10 11 0 43-17 55-17 55-3 2-5 5-5 9l0 32c0 4 3 8 7 10 83 31 127 56 133 73 7 22 9 68 10 88l-43 0c-6 0-11 5-11 11 0 6 5 11 11 11l53 0c6 0 11-5 11-11 0-3 0-74-11-105z"/>
    </symbol>
  
    <symbol id="icon-arrow-down" viewBox="0 0 512 512">
      <path d="m508 109c-4-4-11-3-15 1l-237 269-237-269c-4-4-11-5-15-1-5 4-5 11-1 15l245 278c2 2 5 3 8 3 3 0 6-1 8-3l245-278c4-4 4-11-1-15z"/>
    </symbol>
  
    <symbol id="icon-arrow-left" viewBox="0 0 512 512">
      <path d="m133 256l269-237c4-4 5-11 1-15-4-5-11-5-15-1l-278 245c-2 2-3 5-3 8 0 3 1 6 3 8l278 245c2 2 4 3 7 3 3 0 6-1 8-4 4-4 3-11-1-15z"/>
    </symbol>
  
    <symbol id="icon-arrow-right" viewBox="0 0 512 512">
      <path d="m402 248l-278-245c-4-4-11-4-15 1-4 4-3 11 1 15l269 237-269 237c-4 4-5 11-1 15 2 3 5 4 8 4 3 0 5-1 7-3l278-245c2-2 3-5 3-8 0-3-1-6-3-8z"/>
    </symbol>
</svg>

You can define your own icon sprite on http://fontastic.me/ for free.

And the usage: <Icon name="arrow-down" color="#FFFFFF" size={35} />

And possible add some simple styling for using the icons everywhere:

[class^="icon-"], [class*=" icon-"] {
    display: inline-block;
    vertical-align: middle;
}

Solution 3 - Reactjs

You can directly use .svg extension with img tag if the image is remotely hosted.

ReactDOM.render(
  <img src={"http://s.cdpn.io/3/kiwi.svg"}/>,
  document.getElementById('root')
);

Here is the fiddle: http://codepen.io/srinivasdamam-1471688843/pen/ZLNYdy?editors=0110

Note: If you are using any web app bundlers (like Webpack) you need to have related file loader.

Solution 4 - Reactjs

For some reasons above mentioned approaches did now work for me, before I followed the advice to add .default like this:

<div>
  <img src={require('../../mySvgImage.svg').default} alt='mySvgImage' />
</div>

Solution 5 - Reactjs

You can also import .svg, .jpg, .png, .ttf, etc. files like:

  ReactDOM.render(
      <img src={require("./svg/kiwi.svg")}/>,
      document.getElementById('root')
  );

Solution 6 - Reactjs

if you have .svg or an image locally. first you have to install the loader needed for svg and file-loader for images. Then you have to import your icon or image first for example:

import logo from './logos/myLogo.svg' ;
import image from './images/myimage.png';

const temp = (
     <div>
         <img src={logo} />
         <img src={image} />
     </div>
);

ReactDOM.render(temp,document.getElementByID("app"));

Happy Coding :")

resources from react website and worked for me after many searches: https://create-react-app.dev/docs/adding-images-fonts-and-files/

Solution 7 - Reactjs

Here I found a simple solution without ejecting and we don't need to install other dependencies like react-app-rewired. Because If you want to use SVG as a component we need to update the webpack config of create-react-app.

Method 1:

import { ReactComponent as YourSvg } from './your-svg.svg';

const App = () => (
 <div>
   <YourSvg />
 </div>
);

We can do it like this but it's only on create-react-app-2.0 as per the above answer.

Method 2:

We need to update the webpack configuration of create-react-app.

  1. Go to node_modules/react-scripts/config/webpack.config.js.
  2. Go to the line number 600.

Note:Here you'll see the following info

            // "file" loader makes sure those assets get served by WebpackDevServer.
            // When you `import` an asset, you get its (virtual) filename.
            // In production, they would get copied to the `build` folder.
            // This loader doesn't use a "test" so it will catch all modules
            // that fall through the other loaders.
            {
              loader: require.resolve('file-loader'),
              // Exclude `js` files to keep "css" loader working as it injects
              // its runtime that would otherwise be processed through "file" loader.
              // Also exclude `html` and `json` extensions so they get processed
              // by webpacks internal loaders.
              exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
              options: {
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            // ** STOP ** Are you adding a new loader?
            // Make sure to add the new loader(s) before the "file" loader.
  1. Add the following line to the above file-loader.
         // #1 Custom loader for handling svg images 
            {
              test: /\.svg$/,
              use: ['@svgr/webpack']
            },

That's it 

How to use SVG inside react component?

import ChevronRight from '../../../assets/icons/feather/chevron-right.svg';

const Links = () => {
  return (
          <ChevronRight height={25} width={25} />    
      );
};

export default Links;

Solution 8 - Reactjs

Hard to believe adding a custom icon is so complicated. I found a similar solution to those posted above, but for me, I could not get the icon to display until I added the viewBox info, which I got directly from opening the SVG in a text editor.

//customIcon.js

import React from "react";
import {ReactComponent as ImportedSVG} from "path/to/myIcon.svg";
import { SvgIcon } from '@material-ui/core';

function CustomIcon() {
 return(
  <SvgIcon component={ImportedSVG} viewBox="0 0 384 512"/>

)
}

export default CustomIcon;

I also ran into an error with namespaces and had to clean up the SVG before it would work, following advice from this post

Solution 9 - Reactjs

If you want to use SVG files as React components to perform customizations and do not use create-react-app, do the following:

  1. Install the Webpack loader called svgr
yarn add --dev @svgr/webpack
  1. Update your webpack.config.js
  ...
  module: {
    rules: [
      ...
      // SVG loader
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      }
    ],
  },
  ...
  1. Import SVG files as React component
import SomeImage from 'path/to/image.svg'

...

<SomeImage width={100} height={50} fill="pink" stroke="#0066ff" />

Solution 10 - Reactjs

Just write require with path inside the src of image. it will work. like:

<img alt="Clock" src={require('../assets/images/search_icon.svg')}/>

Solution 11 - Reactjs

You can turn your SVGs to a viable React Component through this site

Solution 12 - Reactjs

I am interesting to know how I can add the SVG as ReactComponent from a remote host, for example from CDN. I would use it as

http://URL/FILE.svg"/> But this is not suitable for my use case.

I would like to see if I can use it as

import { ReactComponent as SvgIcon } from "http://URL/FILE.svg"

Solution 13 - Reactjs

If you have Material UI library in your React project, you can do the follow:

import React from 'react';
import { SvgIcon } from '@material-ui/core';

export function NewIcon() {
  return (
    <SvgIcon viewBox="0 0 48 48"> // you may change the viewBox, so the image will fit into it
      <path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" />
    </SvgIcon>
  )
}

This will automatically change the SVG color when the Theme is changed (Light/Dark). Plus you can change its color and size as you wish e.g.

import React from 'react';
import { styled, SvgIcon } from '@material-ui/core';

const SvgImage = styled(SvgIcon)(() => ({
  height: '40px',
  width: '40px',
  color: 'red',
}));

export function NewIcon() {
  return (
    <SvgImage viewBox="0 0 48 48">
      <path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" />
    </SvgImage>
  );
}

Documentation: https://mui.com/components/icons/#svgicon

Solution 14 - Reactjs

If your SVG includes sprites, here's a component you can use. We have three or four groups of sprites... obviously you can pull that bit out if you only have one sprite file.

The Sprite component:

import React from 'react'
import PropTypes from 'prop-types';

export default class Sprite extends React.Component {
  static propTypes = {
    label: PropTypes.string,
    group: PropTypes.string,
    sprite: PropTypes.string.isRequired
  }

  filepath(spriteGroup)
  {
    if(spriteGroup == undefined) {  spriteGroup = 'base' }
    return "/asset_path/sprite_" + spriteGroup + ".svg";
  }

  render()
  {
    return(
      <svg aria-hidden="true" title={this.props.label}>
        <use xlinkHref={`${this.filepath(this.props.group)}#${this.props.sprite}`}></use>
      </svg>
    )
  }
}

And elsewhere in React you would:

import Sprite from './Sprite';

render()
{
   ...
   <Sprite label="No Current Value" group='base' sprite='clock' />
}

Example from our 'base' sprite file, sprite_base.svg:

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="clock" viewBox="0 0 512 512">
      <path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm216 248c0 118.7-96.1 216-216 216-118.7 0-216-96.1-216-216 0-118.7 96.1-216 216-216 118.7 0 216 96.1 216 216zm-148.9 88.3l-81.2-59c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h14c6.6 0 12 5.4 12 12v146.3l70.5 51.3c5.4 3.9 6.5 11.4 2.6 16.8l-8.2 11.3c-3.9 5.3-11.4 6.5-16.8 2.6z" class="">
      </path>
    </symbol>
    <symbol id="arrow-up" viewBox="0 0 16 16">
      <polygon points="1.3,6.7 2.7,8.1 7,3.8 7,16 9,16 9,3.8 13.3,8.1 14.7,6.7 8,0 "> </polygon>
    </symbol>
    <symbol id="arrow-down" viewBox="0 0 16 16">
      <polygon points="14.7,9.3 13.3,7.9 9,12.2 9,0 7,0 7,12.2 2.7,7.9 1.3,9.3 8,16 "> </polygon>
    </symbol>
    <symbol id="download" viewBox="0 0 48 48">
      <line data-cap="butt" fill="none" stroke-width="3" stroke-miterlimit="10" x1="24" y1="3" x2="24" y2="36" stroke-linejoin="miter" stroke-linecap="butt"></line>
      <polyline fill="none" stroke-width="3" stroke-linecap="square" stroke-miterlimit="10" points="11,23 24,36 37,23 " stroke-linejoin="miter"></polyline>
      <line data-color="color-2" fill="none" stroke-width="3" stroke-linecap="square" stroke-miterlimit="10" x1="2" y1="45" x2="46" y2="45" stroke-linejoin="miter"></line>
    </symbol>
  </devs>
</svg>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKamarajuView Question on Stackoverflow
Solution 1 - ReactjsTsuniView Answer on Stackoverflow
Solution 2 - ReactjsjanhartmannView Answer on Stackoverflow
Solution 3 - ReactjsSrinivas DamamView Answer on Stackoverflow
Solution 4 - ReactjsRomanView Answer on Stackoverflow
Solution 5 - ReactjsHemadri DasariView Answer on Stackoverflow
Solution 6 - ReactjsAbdelaziz El-emaryView Answer on Stackoverflow
Solution 7 - ReactjsMohamed JakkariyaView Answer on Stackoverflow
Solution 8 - ReactjsmattadorView Answer on Stackoverflow
Solution 9 - ReactjsSandroMarquesView Answer on Stackoverflow
Solution 10 - ReactjssanaView Answer on Stackoverflow
Solution 11 - ReactjspythonNoviceView Answer on Stackoverflow
Solution 12 - ReactjsAJ-View Answer on Stackoverflow
Solution 13 - ReactjsLauraView Answer on Stackoverflow
Solution 14 - ReactjsMustModifyView Answer on Stackoverflow