yaboi-hugh
yaboi-hugh

Reputation: 303

React - Generating different Icons within a map function

I have a sidebar components whose list items are generated inside of a map function (movie genres fetched from an api). I would like to have a different icon next to each of the movie genres but have been unable to figure out a way to create a different for each run of the map function.

My thoughts are 1st: make an array of the icons I would like to display, in the order that I would like them to display in.

 const icons = [
    "AiOutlineHome ",
    "FaUserNinja",
    "GiSwordman",
    "GiBabyFace",
    "FaLaughBeam",
    "GiPistolGun",
    "GiPineTree",
    "GiDramaMasks",
    "GiFamilyHouse",
    "GiElfEar",
    "GiScrollUnfurled",
    "GiScreaming",
    "GiMusicalNotes",
    "GiMagnifyingGlass",
    "FaRegKissBeam",
    "GiMaterialsScience",
    "GiHalfDead",
    "GiGreatWarTank",
    "GiCowboyBoot",
  ];

Then in my map function generate a different icon for each list item

{movieGenres.map((genre) => {
            return (
              <li key={genre.id} className="nav-text">
                <button
                  className="genre-btn"
                  onClick={() => genreSelectionHandler(genre.id)}
                >
                  *<GENERATE ICON HERE />*
                  <span className="nav-item-title">{genre.name}</span>
                </button>
              </li>
            );
          })}

Is it possible to pragmatically create components like this? So that I can avoid creating each list item individually if I want different icon.

Upvotes: 3

Views: 11789

Answers (1)

trixn
trixn

Reputation: 16309

You can just take the index of your genre to get the icon. The index is the second argument to the callback of your map() function:

{movieGenres.map((genre, idx) => (
    <li key={genre.id} className="nav-text">
        <button
            className="genre-btn"
            onClick={() => genreSelectionHandler(genre.id)}
        >
            <Icon icon={icons[idx]} />
            <span className="nav-item-title">{genre.name}</span>
        </button>
    </li>
))}

The Icon component would render the icon depending on what kind of icons you are using.

EDIT:

As you want to use react-icons you need to import the actual icon components rather than just using strings:

import {AiOutlineHome} from "react-icons/ai";
import {FaUserNinja} from "react-icons/fa";
// ....

const icons = [
    AiOutlineHome,
    FaUserNinja,
    // ...
];

And render them:

{movieGenres.map((genre, idx) => {
    // must be a capitalized name in order for react to treat it as a component
    const Icon = icons[idx];

    return (
        <li key={genre.id} className="nav-text">
            <button
                className="genre-btn"
                onClick={() => genreSelectionHandler(genre.id)}
            >
                <Icon />
                <span className="nav-item-title">{genre.name}</span>
            </button>
        </li>
    )
})}

Upvotes: 8

Related Questions