Search code examples
javascriptreactjssvgreactstrap

Insert mapped SVGs in React


I'm doing my first bigger React project, and I have already spent a day on this seemingly easy problem. Please excuse mistakes in my terminology.

So I have about a hundred svgs, each put into functions. Since they're so many, I'd rather not touch this file, but if's the only solution, at this point I'm willing to do anything. They're all formatted as such below, except with a lot more svg code, formatted for JSX.

export function Example(props) {
  return (
    <svg viewBox='0 0 100 100' {...props}>
      <g fill='#000000'>
        <path d='long path here' />
      </g>
    </svg>
  );
}

These are put in a picker, that in itself took a whole day to figure it. The problem is, I'm trying to map through them to have one icon selected, and for them to render after being the mapping, but I cannot figure out how.

{icons.map((icon, index) => {
  return (
    <IconMap
      key={index}
        onClick={() => {
        selectIcon(icon);
      }}
    >
    < Example>
    </IconMap>
  );
})}

So they render if I just write , but not with <{icon /> or just {icon}. How can I get the icon being mapped to render out? I'm also quite sure they're "there" so to speak, because I can hover over where they should be, and about the right amount change background color on hover.

I have tried various means, and something that would work would be if I changed my icons file to instead return the svg data as a variable, and then I'd have a separate icon component that rendered it, so I'd essentially write , but it feels like it should be an easier way, where I don't have to re-write hundreds of icons?

And, it's possible that this is an entirely separate question, but as it is something I've been looking into in relation to solving this problem, I'm including it. I'm using reactstrap for this project, and if it would be possible to make a "picker" in reactstrap, such as a dropdown button or a form where the options would show up in a table rather than a list (a vertical list of 100+ icons is a lot of scrolling), I'd gladly hardcode the entire thing just to have it work in reactstrap with the rest of my code.

Thank you so much, and cheers!


Solution

  • Not sure if I understood your question correctly, are you trying to generate the icons dynamically? If so this is one way you can do it

    import Icon1 from 'icons/icon1.svg';
    import Icon2 from 'icons/icon2.svg';
    
    const Icon = (props) => {
      const getIcon = name => {
        return {
          icon1: Icon1,
          icon2: Icon2,
        }
      }
    
      const IconComponent = getIcon(props.name);
      return (
        <IconComponent />
      );
    }
    

    Then you use it in your component like this

    {icons.map((icon, index) => {
      return (
        <IconMap
          key={index}
            onClick={() => {
            selectIcon(icon);
          }}
        >
          <Icon name={icon.name}>
        </IconMap>
      );
    })}