Chances are if you've ever used create-react-app
and you wanted to import an SVG file as a React component, you did something like this and it Just Worked™:
import { ReactComponent as Logo } from './logo.svg'
But, alas, if you have moved to using Vite more often, as I have, you can't just do that.
Never fear, it's still possible!
Enter vite-plugin-svgr
vite-plugin-svgr
is a Vite plugin to transform SVGs into React components! It's super intuitive to use:
npm install vite-plugin-svgr
Add it to your vite.config.js
:
import svgr from 'vite-plugin-svgr'
export default {
// ...
plugins: [svgr()],
// ...
}
And boom, you get your expected behavior!
// somewhere in your React + Vite app
import { ReactComponent as WhateverIcon } from "./icons/WhateverIcon.svg";
// ...
export default function SomeComponent() {
return (
<div>
<WhateverIcon />
Wow, I love icons, because I am a dweeb
</div>
);
}
This is particularly useful if you're using a library like MUI and you need to use a custom icon, like so:
// somewhere in your React + Vite app
import { Box, IconButton, SvgIcon } from "@mui/material";
import { ReactComponent as WhateverIcon } from "./icons/WhateverIcon.svg";
// ...
export default function SomeComponent() {
return (
<Box>
<IconButton aria-label="some icon">
<SvgIcon>
<WhateverIcon />
</SvgIcon>
</IconButton>
Wow, I love icons, because I am a dweeb
</Box>
);
}
There's other things you can do with vite-plugin-svgr
, and there's a list of options here.
Hope that's helpful for ya, happy icon-ing!
Top comments (14)
Nice one, works like a charm. I only have one small problem / question. I'm using TypeScript (v4.9.3), Vite v4.2.0 and vite-plugin-svgr v2.4.0.
I import icon as shown above:
I get a red underline for
ReactComponent
saying:Of course if I use it as suggested, importing a default
the TS error goes away, but can't use it as a React component since this way I just get the asset path as string.
The quick solution that I've found is to add a
// @ts-ignore
above it and move on with my life, but I wonder is there some way to get this working with TS?check this answer stackoverflow.com/a/75818331/10251804
Informative, thank you for sharing!
Thank you so much for this! A great breakdown as I was able to set up the fix using this in a few seconds! Awesome stuff
If you are using vite-plugin-svgr version ^4.0.0 make sure to use the '?react' suffix on your SVG file address:
check out this:
stackoverflow.com/questions/70309561
Ok, serious question: I'm no Vite expert. I have only tested it a bit once. In the project, I have an SVG in the
/assets
folder,react.svg
. It is imported fromApp.jsx
:What's the difference in result between this and what you present? What is the gain?
Long story short, by importing an SVG as a component, you can access the paths and objects in the component. If you use SVGs in
<img>
tags, you don't get to control the innards of the SVG with CSS etc!If you use svgr then you don't need any Img tag.
basically, the svg will render in a img tag on the other hand if you use svgr then it will act like a native html svg elements. it's not like asserts that you have to load after the initial render.
It can render directly
In your case reactLogo use like url, so you can't do some SVG tricks, you can transform only img.
This is interesting, Thank you!
How can I use svgr to import all the svg in the icons folder at once?
current progrewss
Hook
Component
I'm using React Icons and it works fine without this plugin. Have you tried it before?
React Icons already exports SVGs as components. This is for your own custom SVG files that a designer might give to you, not from an existing library.
I see, that's why I never have problem with svg. Thanks