ChatGPT解决这个技术问题 Extra ChatGPT

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

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.


E
Elham Kohestani

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>
);

Bear in mind that ReactComponent name is not optional.
Also, note that the "fill" props are supported for the color change, but make sure default fill props are set with SVG like .
@Jaison I always set it to fill="currentColor" which allows you to style it in code.
@Mordechai after set fill="currentColor" in the svg path internal code, what worked for me was to use the regular color prop, not fill. .
Hm, straight up doesn't work for me. Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
H
Hristo Eftimov

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;
}

The second suggestion doesn't seem to work in Blink and Webkit. Works fine in Firefox though
Interesting - i have another option I use today, which I can update next week. Out of office before.
@janhartmann - Hi, Can you please update the answer as you said?
what do you mean by icon "sprite"? Why can't it be addressed as svg?
You are using SVG fragments here without even mentioning this, which is critical to the answer.
S
Srinivas Damam

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.


I tried do that i dont see the image being displayed, i have local icon
When you say biolerplate what do you mean , i have the image in the same folder so i have something like src={"./abc.icon"}
If you have a local image and using webpack then you need to add file loader as a plugin to your webpack build config.
but it will add it with img tag, it won't have properties of svg
@SrinivasDamam how can we loop if we have 50+ svg files and where we have to store in public or src ?
R
Roman

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

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

Oh man thank you so much for this. The other answers didn't work for me either. Upon adding ".defaut" it worked. Might I ask you how you figured this out? And if you could link a relevant source so I could also understand why this works :)
Thanks for "thank you". I got the idea of the answer indirectly from answers to related questions. So I can not provider you with a link to the documentation. I guess you need to check a specification for the new ".require" version.
Exactly what I needed to use the require function!
THANK YOU @Roman, this was what I actually needed too
Thank you, this worked for me!
A
Abdelaziz El-emary

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/


Thanks, by far, the most convinient method - you have all the attributes - height, width and so on.
Worked for me (not like the other answers). Thanks! (And I'm using create-react-app.)
M
Mohamed Jakkariya

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.

Go to node_modules/react-scripts/config/webpack.config.js. 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.

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;

Note, that this solution requires Webpack.
probably yes for method 2
t
theUtherSide

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

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

Much cleaner imo than using a component! :)
FWIW -- this didn't work for me without using the .default attribute described by @roman above.
m
mattador

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


S
SandroMarques

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

Install the Webpack loader called svgr

yarn add --dev @svgr/webpack

Update your webpack.config.js

  ...
  module: {
    rules: [
      ...
      // SVG loader
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      }
    ],
  },
  ...

Import SVG files as React component

import SomeImage from 'path/to/image.svg'

...

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

s
sana

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

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

p
pythonNovice

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


A
AJ-

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"


L
Laura

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


M
MustModify

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>