Can't import SVG via ReactComponent

I need to import logo.svg, but I'll have to change its colors later on so I can't just import it and use it as src in <img> tag. So I've googled if it's possible to import it as a component and I've got people telling me to do it this way:
import React from 'react';
import { ReactComponent as Logo } from './assets/logo.svg';

function App() {
return (
<div className="App">
<Logo />
</div>
)
}

export default App
import React from 'react';
import { ReactComponent as Logo } from './assets/logo.svg';

function App() {
return (
<div className="App">
<Logo />
</div>
)
}

export default App
But I get a following error: Uncaught SyntaxError: The requested module '/src/assets/logo.svg?import' does not provide an export named 'ReactComponent' (at App.jsx:3:10) I'm in VS code and I can ctrl + click on file path, and it takes me to my logo, so I know file path is not the issue. If anyone experienced this issue and found solution please let me know, if not, do you know other way I can achieve what I want?
11 Replies
Joao
Joao•17mo ago
I would suggest creating a whole new component only for that logo and provide the attributes that you want to customize as props. Import and use that instead of the raw logo.
export function Logo(props) {
return <svg {...props} />
}

// In other files
import { Logo } from './logo';

<Logo fill="" />
export function Logo(props) {
return <svg {...props} />
}

// In other files
import { Logo } from './logo';

<Logo fill="" />
Tenkes
Tenkes•17mo ago
I'd do it if I needed only one, but I need like 10 and I don't want to create new component for each svg... I just found out that ReactComponent works if you use create-react-app to start the project and I'm using Vite so it must be something with that..
Joao
Joao•17mo ago
It's working fine inside codesandbox.io... so it's possible its something to do with the tooling. Can you try this svg just to confirm is not the actual file?
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>.ENV</title><path d="M24 0v24H0V0h24ZM10.933 15.89H6.84v5.52h4.198v-.93H7.955v-1.503h2.77v-.93h-2.77v-1.224h2.978v-.934Zm2.146 0h-1.084v5.52h1.035v-3.6l2.226 3.6h1.118v-5.52h-1.036v3.686l-2.259-3.687Zm5.117 0h-1.208l1.973 5.52h1.19l1.976-5.52h-1.182l-1.352 4.085-1.397-4.086ZM5.4 19.68H3.72v1.68H5.4v-1.68Z"/></svg>
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>.ENV</title><path d="M24 0v24H0V0h24ZM10.933 15.89H6.84v5.52h4.198v-.93H7.955v-1.503h2.77v-.93h-2.77v-1.224h2.978v-.934Zm2.146 0h-1.084v5.52h1.035v-3.6l2.226 3.6h1.118v-5.52h-1.036v3.686l-2.259-3.687Zm5.117 0h-1.208l1.973 5.52h1.19l1.976-5.52h-1.182l-1.352 4.085-1.397-4.086ZM5.4 19.68H3.72v1.68H5.4v-1.68Z"/></svg>
And also just to be sure, it's using this versions or higher?
Note: this feature is available with react-scripts@2.0.0 and higher, and react@16.3.0 and higher.
This may also be useful: https://stackoverflow.com/questions/70309561/unable-to-import-svg-with-vite-as-reactcomponent
Tenkes
Tenkes•17mo ago
I know file is fine since it is working in app created with create-react-app so probably vite didn't include some of the dependencies I need for it I don't even have react-scripts lol
Joao
Joao•17mo ago
Yeah I only read that you are using vite later and I'm guessing that must be it. That thread on stack overflow talks about using a plugin that will parse the svg and make it a component, so I think it's worth a try
Tenkes
Tenkes•17mo ago
It worked! I can use it as component now, thank you!
Joao
Joao•17mo ago
Nice! I'll try to remember that for when using Vite myself as well 🙂
Tenkes
Tenkes•17mo ago
Oof but I can't change fill property through JSX.. that's another issue lol Well I made it work with custom properties for now... I'll try to find better solution tho..
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="24">
<g fill="none" fill-rule="evenodd">
<!-- Here it is ↘ -->
<path fill="var(--clr-logo, #242D52)" fill-rule="nonzero" d="long text here"/>
<g fill="#F3603C">
<path d="long text here" />
<ellipse cx="12.814" cy="13.257" opacity=".5" rx="2.786" ry="2.857" />
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="24">
<g fill="none" fill-rule="evenodd">
<!-- Here it is ↘ -->
<path fill="var(--clr-logo, #242D52)" fill-rule="nonzero" d="long text here"/>
<g fill="#F3603C">
<path d="long text here" />
<ellipse cx="12.814" cy="13.257" opacity=".5" rx="2.786" ry="2.857" />
</g>
</g>
</svg>
<Logo style={{'--clr-logo': 'red'}} />
<Logo style={{'--clr-logo': 'red'}} />
Joao
Joao•17mo ago
Tried quickly again on codesandbox (which uses CRA) and it works fine. It must be again related to the plugin, either it must be configured somehow or it's a limitation it has...
Tenkes
Tenkes•17mo ago
I think when I use fill in component it puts fill attribute to svg element, but I need it on the path tag which is inside of it so that's probably why Yeah I've just tried it in codesandbox with my svg and it doesn't work for me
Joao
Joao•17mo ago
Ahh I see that makes more sense. I think, for something that is already a little more involved than simply importing an existing svg, maybe is worth creating your own implementation At least, that would be my preference