SVG Images as React Components with Webpack
If you’ve ever tried to load inline SVG (using svg-inline-loader) into React, you know it seriously hurts people’s eyes.
import React from "react";
import IconRemove from "./icons/remove.svg";
const RemoveButton = () => (
<button>
<div dangerouslySetInnerHTML={{ __html: IconRemove }} />
<span>Remove</span>
</button>
);
So what if it looked like this instead?
import React from "react";
import IconRemove from "./icons/remove.svg";
const RemoveButton = () => (
<button>
<IconRemove />
<span>Remove</span>
</button>
);
Much better, don’t you think?
That’s what svg-react-loader does. It process your SVG file and returns a React component, which is compiled with Babel (more on this below).
Using the Loader
npm install svg-react-loader --save-dev
Refer to Webpack docs for more information on loaders usage. Also, make sure you have installed svg-react-loader’s dependencies.
1. In Module Request
The simplest method, although the configuration convention is preferred. Using svg-react-loader and babel-loader, import your icon just like:
import IconRemove from "babel!svg-react!./icons/remove.svg";
2. In Webpack Config File (Recommended)
Add in your Webpack configuration file’s loaders
array.
{
test: /\.svg$/,
loader: 'babel!svg-react'
}
Import your icon just like:
import IconRemove from "./icons/remove.svg";
Usage Examples
Loader in module request method (1):
import React from "react";
import IconRemove from "babel!svg-react!./icons/remove.svg";
const RemoveButton = () => (
<button>
<IconRemove />
<span>Remove</span>
</button>
);
Loader in Webpack config file method (2):
import React from "react";
import IconRemove from "./icons/remove.svg";
const RemoveButton = () => (
<button>
<IconRemove />
<span>Remove</span>
</button>
);
A Note on SVG Loaders
Sometimes, we don’t want all of our SVG files to be loaded as React components. If you use a SVG in a img
element, for example, it may lead to conflicts. Fortunately, you can avoid them by being more specific in test
regular expression:
{
test: /\.inline.svg$/,
loader: 'babel!svg-react'
},
{
test: /\.jpe?g$|\.gif$|\.png$|^(?!.*\.inline\.svg$).*\.svg$/,
loader: 'url'
}
Now, only SVG files ending with .inline.svg
will be loaded as React components. You’re good to go!