React, dynamically importing SVG’s

Importing files dynamically

First of all: credit for this solution should go to user dev_junwen at Stackoverflow for this excellent answer:

Rendering SVG’s on a website can be made in a couple of different ways. I will be focusing on a particular way it can be done in React, which gives us some neat advantages.

Here’s what I want to achieve:

  • Import all SVG’s from a folder at runtime, i.e based on props
  • Render the SVG as a React component, as in <MySvg />

❌ Importing the components dynamically removes the need to do a manual import on all our SVG’s like:

Why not render as <img> tag ?

One common question is why to not just render them as

The reason I want to render as <MySvg /> instead is that I can pass in some important props, fill, width and height, which isn’t valid properties on a img tag. This will let us control the size and fill color of the SVG, which is a common use case for, let’s say, an icon library.

✅ So, here’s all the magic:

Basically, we make use of two important things here, webpack’s import function, and React’s useRef function, but we also import a non default exported module, which is not very common and is what made this tricky for me to understand from the beginning.

When our component receives its props, it looks for an update in the name prop, and runs the importIcon function, which imports the SVG file, extracts the component from it and assigns it to our ref. The weird part here is the default, which is easy to miss.

Let’s say we would only import the file and call it esModule, then put a debugger right after and have a look at esModule , this is what we have:

So we get an object which has adefault property, which is a function that returns a component. In this case the component is Econ , because the name we passed in is “econ” —so we are trying to import a “econ.svg”.

The difference here from a more common import MyComponent from './components/MyComponent' , is that our module is not default exported, as in export default MyComponent , and so we need to destructure and rename the “default” key (because default is a reserved keyword) from the returned object in order to actually render it. The way we do that is:

const { default: namedImport } = await import(`./icons/${name}.svg`)

This is what makes it possible to render the imported SVG as a component. Now we can easily render our SVGs without manual imports!

🍻And that’s it! Hope it helped. If you liked this article, please give me one of those clapping hands, and if you hated this article, let me know in the comments so I can get better! :)

— Eric

Twitter: @ercintheloft



Developer, person and conscious meat bag. Making products and trying to learn how to write about it.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Eric Khoury

Developer, person and conscious meat bag. Making products and trying to learn how to write about it.