skip to Main Content

I have multiple Icon components like this:

import { IconProps } from "@utils/types";

const FilterIcon = (props: IconProps) => {
  const { fillColor, width, height } = props;

  return (
    <svg
      width={width}
      height={height}
      viewBox="0 0 24 24"
      fill="white"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M17.625 12C1..."
        fill={fillColor}
      />
    </svg>
  );
};

export default FilterIcon;

the problem is that I have almots 40 of them in different files. I want to make a component to use them in a better way, something like this:

<Icon name="IconName" width="20px" height="20px" fillColor="white" />

where name could be an enum type or similar

I made a huge Icon component that imports all the icons and uses a switch to return an icon component (130 lines…)

2

Answers


  1. First, you can declare a barrel file:

    // icons/index.ts
    export { default as FilterIcon } from './FilterIcon.tsx'
    // ...
    

    And then create an <Icon> component:

    // icon.tsx
    import * as icons from './icons'
    
    export const Icon = ({ name, ...props }: {
      name: keyof typeof icons,
      // other props
    }) => {
      const Component = icons[name]
      return <Component {...props} />
    }
    
    Login or Signup to reply.
  2. Instead of using a switch statement, you can utilize a mapping object to map icon names to their respective components.

    import React from 'react';
    import { IconProps } from '@utils/types';
    import FilterIcon from './FilterIcon'; // Import your individual icon components
    
    // Map icon names to their respective components
    const iconComponents: Record<string, React.FC<IconProps>> = {
      FilterIcon,
      // Add more icons here as needed
    };
    
    type IconName = keyof typeof iconComponents;
    
    interface Props extends Omit<IconProps, 'fillColor'> {
      name: IconName;
      fillColor?: string;
    }
    
    const Icon: React.FC<Props> = ({ name, fillColor = 'white', ...rest }) => {
      const IconComponent = iconComponents[name];
    
      if (!IconComponent) {
        console.error(`Icon component "${name}" not found.`);
        return null;
      }
    
      return <IconComponent {...rest} fillColor={fillColor} />;
    };
    
    export default Icon;
    

    and then you can use like below:-

    <Icon name="FilterIcon" width="20px" height="20px" fillColor="white" />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search