skip to Main Content

I have react component named IconRenderer and I’m passing 2 props named iconName and iconPath. What the IconRenderer do is it imports react-icon module using lazyload by taking the iconPath and iconName

The following is my IconRenderer component

type Props = {
  iconName: string;
  iconPath: string;
};
const IconRenderer = (props: Props) => {
  const { iconName, iconPath } = props;
  const path = `react-icons/${iconPath}`

  const Icon = lazy(async () => {
    const module = await import(path);
    return { default: module[iconName] };
  });
  console.log(Icon);


  return (
    <Suspense fallback={<div>Loading...</div>}>
      <IconContext.Provider value={{ size: "3em" }}>
        <Icon />
      </IconContext.Provider>
    </Suspense>
  );
};

export default IconRenderer;

I’m using this IconRenderer component in the APP.tsx as below

<IconRenderer iconName="FaAccessibleIcon" iconPath="fa" />

When importing the module, it says the following error

Cannot find module 'react-icons/fa'

Anyhow when importing the module by directly passing the path without assigning it to a variable as below, it works

 const Icon = lazy(async () => {
    const module = await import(`react-icons/fa`);
    console.log(module)
   
    return { default: module[iconName] };
  });
  

What i want is to import the module by taking the variable path

2

Answers


  1. const Icon = lazy(async () => {
      const module = await import(`react-icons/${iconPath}`);
      return { default: module[iconName] };
    });
    

    This ensures that the dynamic import uses the correct path at runtime. Storing the path in a variable ( const path = react-icons/${iconPath} ) may lead to issues, especially if the dynamic import is unable to resolve the path correctly in certain situations.

    Login or Signup to reply.
  2. I don’t think, this will be a good idea to have this kind of a component for rendering icons dynamically.

    Most of the time as a developer, we tend to create constants or some sort of reference for assets like icons, images, fonts, or any other frequently used string. So, I think you should create an index of all the icons in one place like this.

    import { AiFillApple } from "react-icons/ai"
    
    export const iconsIndex = {
      AiFillApple: <AiFillApple />
    }
    

    Then, we don’t have to worry about inconsistent icons all over the app. We can reference the index and change it once, every other instance of it will also be updated.

    Then, we can create a wrapper component, that wraps the icons with the styles we might need. We can add here default styles that will be applied to all.

    import React from 'react'
    
    const IconsWrapper = ({ icon, ...props }) => {
      return (
        <div style={{ fontSize: 70 }} {...props}>
          {icon}
        </div>
      )
    }
    
    export default IconsWrapper
    

    And we can use this component and add styles specific to use cases, later on while using the Wrapper.

    import React from 'react'
    import IconsWrapper from "./components/IconWrapper/Wrapper"
    import { iconsIndex } from "./components/IconWrapper/IconsIndex"
    
    const App = () => {
      return (
        <div>
          <IconsWrapper icon={iconsIndex.AiFillApple} />
          <IconsWrapper style={{fontSize: 50}} icon={iconsIndex.AiFillApple} />
        </div>
      )
    }
    
    export default App
    

    This feels much more intuitive and we are writing re-usable components and constants, which can be used over and over with customized styles.

    I hope you find this way of rendering icons helpful. Let me know if you liked it this way.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search