spas2k
spas2k

Reputation: 519

React - Map dynamic component name within map loop

I'm new to react and trying to create a menu bar of sorts. All the similar questions seem to be older or not quite what I need. Regardless, I can't get this to work so please help figuring this out.

I'm using react-icons and would like to dynamically name the component so I can use the icons within this loop but <{val.icon} /> is throwing an error: "'...' expected." What can I do to make this work? I also can't seem to declare variables in a return statement to work around this, or at least I can't figure out how to do so. Any idea?

   const values = [
    { id: 1, text: "Home", icon: "MdHomeFilled" },
    { id: 2, text: "Schedule", icon: "MdEditCalendar" },
    { id: 3, text: "Scores", icon: "MdSportsTennis" },
    { id: 4, text: "Stats", icon: "IoIosStats" }
    ];

return (
    <>
       
            <ul>

                {values.map((val) => (
                    <li onClick={() => setActiveId(val.id)}>
                        <div className={activeId === val.id ? "NavLinkBox selected":"NavLinkBox"}>
                            <div className="navLinkBoxHdr"><{val.icon} /></div>
                            <div className="navLinkBoxCnt">{val.text}</div>
                        </div>
                    </li>
                ))}
            </ul>

Upvotes: 0

Views: 2165

Answers (2)

Chandradeep Chandra
Chandradeep Chandra

Reputation: 1

Use it like this:

const socialArr = [
[
  "Linkedin",
  <TiSocialLinkedinCircular size={30} style={{ color: "grey" }} />,
],
["Github", <AiFillGithub size={25} style={{ color: "grey" }} />],
["Facebook", <BsFacebook size={24} style={{ color: "grey" }} />],
["Twitter", <AiFillTwitterCircle size={25} style={{ color: "grey" }} />],
["Instagram", <AiFillInstagram size={25} style={{ color: "grey" }} />],
["Website", <BsGlobe size={25} style={{ color: "grey" }} />],  ];


{socialArr.map(([name, icon]) => (
      <>
        <div className="web__bottom__tab">
          <h2>{name}</h2>
          <div className="web__input">
            {icon} // here is the icon that will be rendered
            <input type="text" placeholder={name} />
          </div>
        </div>
      </>
    ))}

Upvotes: 0

GalAbra
GalAbra

Reputation: 5148

You can't just use a component name (i.e. as a string) in order to render a component.

In order to render it, you need to import it like you would regularly, then convert it into a variable with a capitalized name. For example:

import MdHomeFilled from './MdHomeFilled';
import MdEditCalendar from './MdEditCalendar';

export default function App() {
  const values = [
    { id: 1, text: "Home", icon: MdHomeFilled },
    { id: 2, text: "Schedule", icon: MdEditCalendar }
  ];

  return ( 
    <ul>
        {values.map((val) => {
          const IconComponent = val.icon; // This way you can use this field as a component
          return (
            <li key={val.id} onClick={() => setActiveId(val.id)}>
                <div className={activeId === val.id ? "NavLinkBox selected":"NavLinkBox"}>
                    <div className="navLinkBoxHdr"><IconComponent /></div>
                    <div className="navLinkBoxCnt">{val.text}</div>
                </div>
            </li>
          );
        })}
    </ul>
  );
}

Upvotes: 2

Related Questions