is there a better way to render a set of 50+ svg icons in another component without using the exact path of files with the svg extension

enter image description hereim so exhausting of trying to get the functionality of the exact design attached in this Picture, I do not know how to import/render these reusable SVG icons shown in the second picture without having to import every single icon path from local files !

please any kind of help or support will be highly appreciated

import React, { useEffect, useState } from "react";

function Icon({ name, ...otherProps }) {
  /* Use state hook to store icon module value */
  const [iconModule, setIconModule] = useState(null);

  useEffect(() => {
    /* Use dynamic import to get corresponding icon as a module */
    import(`./icons/${name}.svg`)
      .then((module) => {
        /* Persist data in state */
        setIconModule(module);
      })
      .catch((error) => {
        /* Do not forget to handle errors */
        console.error(`Icon with name: ${name} not found!`);
      });
  }, [name /* update on name change */]);

  const renderIcon = () => {
    if (!iconModule) return null;

    /**
     * Equal to:
     * import { ReactComponent as Icon } from "./path/to/icon.svg";
     */
    const Component = iconModule.ReactComponent;

    return <Component {...otherProps} />;
  };

  return <>{renderIcon()}</>;
}

export default Icon;

Example image

2 answers

  • answered 2021-09-11 18:20 BILAL

    You can take a look at the SVG sprite it make use of sprite file, so you won't be referencing the path over and over agian.

    For more details on sprite file

  • answered 2021-09-11 18:29 windmaomao

    Ok, svg is also a DOM element. So <svg /> can be exported from a valid component.

    import createSvgIcon from './createSvgIcon'
    
    const BackArrowIcon = createSvgIcon(
      <g transform="translate(-12.75 -99.75)">
        <path transform="translate(13 100)" />
      </g>
    )
    
    export default BackArrowIcon
    
    

    Just an idea, which is similar to yours.

    import { memo } from 'react'
    import styled from 'styled-components'
    
    const size = '24px'
    const stroke = (props: any) => props.stroke || '#bbb'
    const fill = (props: any) => props.fill || 'none'
    const strokeWidth = '0.5px'
    
    const IconStyle = styled.svg`
      width: ${size};
      height: ${size};
      fill: ${fill};
      stroke: ${stroke};
      stroke-width: ${strokeWidth};
      stroke-miterlimit: 10;
    `
    
    function createSvgIcon(path: any) {
      return memo((props: SvgIconProps) => (
        <IconStyle {...props}>
          {path}
        </IconStyle>
      ))
    }
    
    export default createSvgIcon
    

    The major difference is that i didn't use dynamic import, so svg file isn't a resources, instead it becomes part of a component of React.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum