'How do I toggle the elements with its corresponding button by mapping through an array in ReactJS?

<div>
    {arrayOfDetails.map((deets, index) => (
            <div>
                <h1>{deets.firstName + ' ' + deets.lastName}</h1>
                <div>
                    <div id={index}>
                        {listOfGrades(deets.grades)}
                    </div>
                </div>
                <button type="button" data-toggle="button" aria-pressed="false" autoComplete="off">+</button>
            </div>
    ))}
</div>

I'm mapping through an array from a JSON. How do I get the button to toggle the display of the div containing listOfGrades with the ID?

So 20 buttons for 20 listOfGrades divs, and each button should toggle its own corresponding div.

Thanks!



Solution 1:[1]

You can add a property in your data which keeps track of the hidden state. Then on button click for a row, find the index and toggle hidden property for that row.

  const [deets, setDeets] = useState([]); // Set initial Value here with hidden property for each item in array

  const toggleElement = (idx) => {
    let newDeets = [...deets];
    deets[idx].hidden = !deets[idx].hidden;
    setDeets(newDeets);
  };

  return (
    <div>
      {arrayOfDetails.map((deets, index) => (
        <div>
          <h1>{deets.hidden ? "" : `${deets.firstName} ${deets.lastName}`}</h1>
          <div>
            {deets.hidden ? (
              ""
            ) : (
              <div id={index}>{listOfGrades(deets.grades)}</div>
            )}
          </div>
          <button
            type="button"
            data-toggle="button"
            aria-pressed="false"
            autoComplete="off"
            onClick={() => toggleElement(index)}
          >
            +
          </button>
        </div>
      ))}
    </div>
  );

Solution 2:[2]

add a property isActive to each data object.

for example :

setArrayOfDetails(dataComingFromServer.map(item=>({...item,isActive:true})))

create the callback for toggling active status:

const toggleActive=(index)=>{

 const newState=[...arrayOfDetails]
 newState[i].isActive=!newState[i].isActive
 setArrayOfDetails(newState)
}

now render the items that are active:

<div>
{arrayOfDetails.map((deets, index) => (
        <div>
            <h1>{deets.firstName + ' ' + deets.lastName}</h1>
             <div>
             {deets.isActive &&  <div id={index}>
                    {listOfGrades(deets.grades)}
                </div>}
            </div>
            <button type="button" data-toggle="button" aria-pressed="false" autoComplete="off" onClick={()=>toggleActive(index)}>+</button>
        </div>
))}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PR7
Solution 2