I’m sure we all have at least one application where for one reason or another decided not to use an icon library. Sometimes you just want hand made icons, images in your app that truly reflects your brand. Or you are just against importing a whole icon library when you only plan to use 1–2 of them.
Now using our own icons also has its drawbacks. One of them that I dislike the most is SVG file imports, especially if you have many icons in the same component. This article will aim to give a more readable and flexible solution for this problem.
For this article you can find a Github repo here. It’ll contain some SVG files if you’d like to follow along.
To show the problem we are facing with multiple imports, let’s assume a scenario. One where we have 6 icons in the same component. This code snippet is what I usually see when something like that happens:
import "./App.css";
import ClockIcon from "./icons/clock.svg";
import ContactIcon from "./icons/contact.svg";
import DownloadIcon from "./icons/download.svg";
import FileIcon from "./icons/file.svg";
import FingerprintIcon from "./icons/fingerprint.svg";
import StarIcon from "./icons/star.svg";
function App() {
return (
<div className="App">
<img src={ClockIcon} alt="clock" />
<img src={ContactIcon} alt="contact" />
<img src={DownloadIcon} alt="download" />
<img src={FileIcon} alt="file" />
<img src={FingerprintIcon} alt="fingerprint" />
<img src={StarIcon} alt="star" />
</div>
);
}
export default App;
Now let’s see how we can improve this. First, I’ll create a file that’ll have one job and one job only. Import all the available icons and store them as an object. I’ll do this so I can store everything in one place, and retrieve a single object by name when I need it. With that, let’s create a new file in our components
folder called icons.js
and it’ll look something like this:
import { ReactComponent as Clock } from "../icons/clock.svg";
import { ReactComponent as Contact } from "../icons/contact.svg";
import { ReactComponent as Download } from "../icons/download.svg";
import { ReactComponent as File } from "../icons/file.svg";
import { ReactComponent as Fingerprint } from "../icons/fingerprint.svg";
import { ReactComponent as Star } from "../icons/star.svg";
const icons = {
Clock,
Contact,
Download,
File,
Fingerprint,
Star,
};
export default icons;
It’s time to create our reusable Icon
component. This’ll use our icons
object from above and will accept a name
prop that we’ll use to select the correct icon from the many and return it as a component. Let’s create a new file in our components
folder called Icon.js
and this is how our component will look like:
import React from "react";
import icons from "./icons";
export const Icon = ({ name }) => {
const SelectedIcon = icons[name];
if (!SelectedIcon) return "";
return <SelectedIcon />;
};
export default Icon;
And this is how you can use our new component in App.js
import "./App.css";
import Icon from "./components/Icon";
function App() {
return (
<div className="App">
<Icon name="Clock" />
<Icon name="Contact" />
<Icon name="Download" />
<Icon name="File" />
<Icon name="Fingerprint" />
<Icon name="Star" />
</div>
);
}
export default App;
Of course we could still reduce the amount of lines by storing all our icon names in an array and map through it. I decided not to do it because even though it’d reduce our lines of code, it’d also make it less readable. You can go ahead if you prefer it that way though, it’s just a personal preference of mine.
That wraps up this article, but we could continue by extending this component. Now that it’s a standalone React component, we can add event handlers to it with ease, add custom styling as it’ll accept a className
as any other component and apply the styles you define. The possibilities are endless. Give it a try and you’ll see yourself!