Let's say I have a dozen or more SVGs that I want to inline in my React app. Right now, I'm using svg-react-loader to import them like this.
import Svg1 from "!babel!svg-react!../../images/sdg1.svg";
import Svg2 from "!babel!svg-react!../../images/sdg2.svg";
import Svg3 from "!babel!svg-react!../../images/sdg3.svg";
import Svg4 from "!babel!svg-react!../../images/sdg4.svg";
...and so on. I need to set event handlers on each of them and hover events. Moreover, when one of them is selected I want to change its opacity.
After several hours and as many failed experiments, the only thing I've tried that works is to render them all inside a parent component like this.
const Icon = React.createClass({
//Callback that updates the state of a parent component
clickHandler() {
this.props.handler(this.props.svg)
}
render() {
const icons = [
<Svg1 className="svg1" opacity={this.props.svg === this.props.currentSvg ? 1 : 0.3} />
<Svg2 className="svg2" opacity={this.props.svg === this.props.currentSvg ? 1 : 0.3} />
<Svg3 className="svg3" opacity={this.props.svg === this.props.currentSvg ? 1 : 0.3} />
<Svg4 className="svg4" opacity={this.props.svg === this.props.currentSvg ? 1 : 0.3} />
];
return (
<div className="icon" onClick={this.clickHandler}>
{icons[this.props.svg]}
</div>
);
}
});
Again, this works but I'm sure this isn't the way React intended. Is there a way to iterate over SVG components created this way to assign them properties?
one way is to just put them in an array and use React.createElement:
const icons = [Svg1, Svg2, Svg3, Svg4];
return (
<div className="icon" onClick={this.clickHandler}>
{icons.map((svg, i) => React.createElement(svg, {
className: "svg"+i,
opacity: (this.props.svg === this.props.currentSvg ? 1 : 0.3)
})}
</div>
);
Another option, since you are using Webpack is to make use of their dynamic require functionality.
Basically you can give webpack a wildcard of files to bundle with your app and then at runtime dynamically and synchronously require them:
// right below your import statements
const reqSvgs = require.context("../../images", false, /\.svg$/);
// now anywhere in your code you can:
const arrayOfSVGFilenames = reqSvgs.keys();
const specificSVG = reqSvgs("../../images/svg1.svg");
const allSVGsInAnArray = reqSvgs.keys().map(reqSvgs);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With