I have a component that takes in an :itemName and spits out an html bundle containing an image. The image is different for each bundle.
Here's what I have:
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import SVGInline from "react-svg-inline";
export default (props) => (
<NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}> {React.createElement(SVGInline, {svg: props.itemName})} </NavLink>
)
How could I make this component work?
I know that if I just imported all my images explicitly, I could just call my images like so...
import SVGInline from "react-svg-inline";
import SASSSVG from "./images/sass.svg";
<NavLink className="hex" activeClassName="active" to="/hex/sass"><SVGInline svg={ SASSSVG } /></NavLink>
This would work, but since I need to include ~60 svgs, it adds A LOT of excess code.
Also, I found in this question this code...
import * as IconID from './icons';
But that doesn't seem to work (it was part of the question, not the answer), and the answer was a bit too nonspecific to answer the question I'm asking.
I also found this question but again there's an answer (although unapproved) that possess more questions than it answers. So, after installing react-svg, I set up a test to see if the answer works like so...
import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import { NavLink } from 'react-router-dom';
import ReactSVG from 'react-svg'
export default (props) => (
<NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}>
<ReactSVG
path={"images/" + props.itemName + ".svg"}
callback={svg => console.log(svg)}
className="example"
/>
</NavLink>
)
But, just as the OP of that question was asking, the page can't find my svg even after copying my entire image folder into my build folder. I've also tried "./images/"
I feel like I'm just missing one last key piece of information and after searching for the past day, I was hoping someone could identify the piece I'm missing.
Stumbled onto this issue - I initially had the "Accepted answer", but i caused http request for each and every svg, which triggered a rate limit. So I ended up with a combination the accepted answer and what @karthik proposed - using a loader in the request.context
As of CRA 2.0 @svgr is included to import svg's as react components.
So here we combine an svg loader and require.context
Then we map all these into a json object so we can use key lookup
To render svg's in jsx:
And happy days, svgs included in bundle and no individual http requests
Instead of multiple SVG files you can use the single SVG sprite.
SVG sprite can be generated from a directory of SVG files using svg-sprite-generator:
Then use it like this:
You can simply make a function which takes a parameter "name" (your svg icon name) and return your svg code.
import React from 'react' export function getIcon(name){ switch(name) { case 'back': return ( // your svg code here <svg></svg> ) } }
And then you can import it anywhere and simply call it with icon name you want.
Best way is to use a node module like [SVG to React Loader] (https://github.com/jhamlet/svg-react-loader)
If using React, I strongly suspect you are also using Webpack. You can use
require.context
instead of es6import
and Webpack will resolve it for you when building.The first line of each example ...
... creates a Require Context mapping all the
*.svg
file paths in theimages
folder to an import. This gives us a specialized Require Function namedreqSvgs
with some attached properties.One of the properties of
reqSvgs
is akeys
method, which returns a list of all the valid filepaths.We can pass one of those filepaths into
reqSvgs
to get an imported image.This api is constraining and unintuitive for this use case, so I suggest converting the collection to a more common JavaScript data structure to make it easier to work with.
Every image will be imported during the conversion. Take care, as this could be a foot-gun. But it provides a reasonably simple mechanism for copying multiple files to the build folder which might never be explicitly referenced by the rest of your source code.
Here are 3 example conversions that might be useful.
Array
Create an array of the imported files.
Array of Objects
Create an array of objects, with each object being
{ path, file }
for one image.Plain Object
Create an object where each path is a key to its matching file.
SurviveJS gives a more generalized example of
require.context
here SurviveJS Webpack Dynamic Loading.