Home > other >  How do I access specific items in a mapped list through an onClick?
How do I access specific items in a mapped list through an onClick?

Time:10-23

So I'm losing my mind over here trying to essentially just select the sibling element of things that are mapped.

I basically map over an object from an API, grab some stuff from it, and display some text and an ul with some li in it. I ultimately want to click on h2 and have it alter the ul below it. In this case, I want the ul item below it to have a display of none until clicked. I also tried returning the JSX of the ul in the onClick of the h2 tag, but it didn't add any elements to the page.

This wouldn't be so bad if I knew what anything was going to be, and it was a set object, but being an API, I could have 1 or 1000 ul to work with that all need the same functionality. I was reading to do it by state, but I don't know how many items there are going to be, so how would I set state on an undefined number of items? Also, wouldn't having 100 states for this be crazy if that's what my API returned??

    return myData.map((obj) => (
  <div style={{ maxWidth: "500px", marginLeft: "25%" }} key={obj.name}>
    <img
      src={obj.image}
      width="500px"
    ></img>
    <h1>{obj.name}</h1>
    <h2 id={'ingredients' Math.Random} onClick={(e) => {console.log(e)}}>Ingredients</h2>
    <ul id={'UL' Math.random()}>
      {obj.ingredients.map((index) => (
        <ListItem  key={"ingredients"   Math.random()} value={index} />
      ))}
    </ul>

Side note - this code is ultimately for my practice only, so ignore bad naming etc...

CodePudding user response:

You can achieve this by only using one state. Assuming your obj.name is unique since you are using it as a key value. You can use this name to determine wheter or not to display your ul, if the id is in the array then display the ul, if not do not display.

const YourComponent = () => {
  // state to track all the ids of all the expanded ul's
  const [expandedIds, setExpandedIds] = useState([]);

  const toggleVisibility = (idToToggle) => {
    // set new state
    setExpandedIds((prevIds) => {
      // if the id to toggle is in the array, if not add it
      if (!expandedIds.includes(idToToggle)) return [...prevIds, idToToggle];
      // else remove the id
      return prevIds.filter((id) => id !== idToToggle);
    });
  };

  return myData.map((obj) => (
    <div style={{ maxWidth: "500px", marginLeft: "25%" }} key={obj.name}>
      <img src={obj.image} width="500px"></img>
      <h1>{obj.name}</h1>
      <h2 onClick={() => toggleVisibility(obj.name)}>Ingredients</h2>
      {expandedIds.includes(obj.name) && (
        <ul id={"UL"   Math.random()}>
          {obj.ingredients.map((index) => (
            <ListItem key={"ingredients"   Math.random()} value={index} />
          ))}
        </ul>
      )}
    </div>
  ));
};

I hope this helps you with your project.

  • Related