When I first started building React applications, I noticed something: every time I needed an icon, I ended up repeating the same lines of code. Whether it was a shopping cart for an eCommerce dashboard or a location pin for a U.S. map app, I kept importing and styling icons individually.
After years of experience working with reusable React components, I realized that creating a reusable Icon component not only saves time but also keeps your codebase clean and consistent. In this tutorial, I’ll show you how I build one step-by-step, the same approach I use in my own projects.
Create a Reusable Icon Component
If you’ve ever worked on a large React project, you know how quickly icons can get messy. One developer imports from react-icons/fa, another from @mui/icons-material, and suddenly, your app has multiple icon libraries bloating the bundle.
A reusable icon component solves this problem by:
- Centralizing icon imports
- Maintaining consistent styling
- Making it easier to switch icon libraries later
It’s one of those small investments that pays off big time as your app grows.
Method 1 – Create a Simple Reusable Icon Component (Using React Icons)
Let’s start with the simplest way to build a reusable icon component using the react-icons library.
Step 1: Install React Icons
npm install react-iconsStep 2: Create the Icon Component
In your src/components folder, create a file called Icon.tsx.
import React from "react";
import * as FaIcons from "react-icons/fa";
import * as MdIcons from "react-icons/md";
type IconLibrary = "fa" | "md";
interface IconProps {
name: string;
library?: IconLibrary;
size?: number;
color?: string;
className?: string;
}
const Icon: React.FC<IconProps> = ({
name,
library = "fa",
size = 24,
color = "#000",
className = "",
}) => {
const libraries = {
fa: FaIcons,
md: MdIcons,
};
const SelectedLibrary = libraries[library];
const IconComponent = (SelectedLibrary as any)[name];
if (!IconComponent) {
console.warn(`Icon "${name}" not found in library "${library}"`);
return null;
}
return <IconComponent size={size} color={color} className={className} />;
};
export default Icon;Step 3: Use the Icon Component
Now, you can use it anywhere in your app:
import React from "react";
import Icon from "./components/Icon";
const Dashboard = () => {
return (
<div style={{ padding: "20px" }}>
<h2>My Dashboard</h2>
<Icon name="FaShoppingCart" library="fa" color="#0d6efd" size={30} />
<Icon name="MdLocationOn" library="md" color="crimson" size={28} />
</div>
);
};
export default Dashboard;I executed the above example code and added the screenshot below.

That’s it! You now have a reusable icon component that can load icons dynamically from multiple libraries.
Method 2 – Add TypeScript Safety and Customization
When I work on production-grade applications, I prefer strong typing and flexibility. Let’s enhance our component with TypeScript generics and custom styles.
Step 1: Extend the Props
We’ll add a style prop and improve type safety.
import React, { CSSProperties } from "react";
import * as FaIcons from "react-icons/fa";
import * as MdIcons from "react-icons/md";
type IconLibrary = "fa" | "md";
interface IconProps {
name: string;
library?: IconLibrary;
size?: number;
color?: string;
className?: string;
style?: CSSProperties;
}
const Icon: React.FC<IconProps> = ({
name,
library = "fa",
size = 24,
color = "#000",
className = "",
style,
}) => {
const libraries = { fa: FaIcons, md: MdIcons };
const SelectedLibrary = libraries[library];
const IconComponent = (SelectedLibrary as any)[name];
if (!IconComponent) {
console.warn(`Icon "${name}" not found in library "${library}"`);
return null;
}
return (
<IconComponent
size={size}
color={color}
className={className}
style={style}
/>
);
};
export default Icon;Step 2: Example Usage with Custom Styles
<Icon
name="FaUserCircle"
library="fa"
color="#198754"
size={40}
style={{ marginRight: "10px", verticalAlign: "middle" }}
/>I executed the above example code and added the screenshot below.

This gives you full control over the icon’s appearance while keeping your code DRY (Don’t Repeat Yourself).
Method 3 – Use a Config File for Centralized Icon Management
In larger U.S.-based enterprise apps (like dashboards or CRMs), you might have hundreds of icons. Instead of remembering icon names, you can manage them in a single file.
Step 1: Create an Icon Map
// src/icons/IconMap.ts
export const IconMap = {
cart: { name: "FaShoppingCart", library: "fa" },
user: { name: "FaUserCircle", library: "fa" },
location: { name: "MdLocationOn", library: "md" },
};Step 2: Use the Map in the Component
import React from "react";
import Icon from "../components/Icon";
import { IconMap } from "../icons/IconMap";
const Header = () => {
return (
<header style={{ display: "flex", alignItems: "center", gap: "10px" }}>
<Icon {...IconMap.cart} color="#007bff" size={28} />
<Icon {...IconMap.user} color="#28a745" size={28} />
<Icon {...IconMap.location} color="#dc3545" size={28} />
<h3>My U.S. E-commerce Dashboard</h3>
</header>
);
};
export default Header;I executed the above example code and added the screenshot below.

Now, if you ever want to switch from Font Awesome to Material Icons, you just update the IconMap file, and your entire app updates automatically.
Method 4 – Add Lazy Loading for Performance
For large applications, performance matters. You can lazy-load icons so they only load when needed.
import React, { Suspense } from "react";
const Icon = ({ name, library = "fa", ...props }) => {
const IconComponent = React.lazy(() =>
import(`react-icons/${library}/index.js`).then((module) => ({
default: module[name],
}))
);
return (
<Suspense fallback={<span>Loading...</span>}>
<IconComponent {...props} />
</Suspense>
);
};
export default Icon;This approach ensures your initial bundle remains lightweight, perfect for apps targeting U.S. users with varying internet speeds.
Bonus Tip – Theme Your Icons
If your React app supports dark and light modes, you can theme your icons easily.
const theme = {
light: "#000",
dark: "#fff",
};
<Icon name="FaSun" color={theme.light} />
<Icon name="FaMoon" color={theme.dark} />;You can even make the theme dynamic using React Context or a global state manager like Redux or Zustand.
I’ve used this approach in multiple production apps, from analytics dashboards to internal business tools, and it has saved me countless hours. Building a reusable icon component might seem like a small improvement, but it brings consistency, scalability, and flexibility to your React projects.
Once you start using it, you’ll never go back to manually importing icons again.
You may also like to read:
- Extend Functional Components in ReactJS
- How to Create a React Header Component
- Build a Custom React Progress Bar Component
- Override a Styled Component in React

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.