Build a Reusable Icon Component in React

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-icons

Step 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.

Build Reusable Icon Component in React

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.

Build a Reusable Icon Component in React

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.

Build Reusable Icon Component React

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:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.