[SOLVED] How can I set state on individual elements in a mapped function using React?

Issue

I have an array of questions that I’m mapping through and displaying them in the UI, there is about 70+ questions.

Each question has a '+' button that reveals an answer when clicked, I want to reveal the answer using state but only for the specific question that is clicked, not the entire list. Currently I have it so when a button is clicked, it reveals all 70+ answers, what’s the best way to do this so it only reveals one?

This is my code:

  const [open, setOpen] = useState(false);


 <div className='md:mt-8 pb-20'>
            {results[0].data.glossary_boxes.map((item, i) => (
              <>
                <div
                  key={i}
                  className='w-full border-3 border-yellow-500 flex-grow p-2 md:p-2 my-8'>
                  <div className='flex h-full items-center'>
                    <div className='bg-yellow-500 px-3 py-1 flex items-center justify-start ml-2'>
                      <a
                        onClick={() => setOpen(!open)}
                        className='text-white text-3xl cursor-pointer'>
                        {open ? '-' : '+'}
                      </a>
                    </div>
                    <div className='flex flex-col items-start'>
                      <p className='text-gray-500 font-sansbold text-md md:text-xl px-12'>
                        {item.question}
                      </p>

                      <p
                        className={`text-xl gray-500 font-quote text-md md:text-lg px-12 ${
                          open ? 'block' : 'hidden'
                        }`}>
                        {item.answer}
                      </p>
                    </div>
                  </div>
                </div>
              </>
            ))}
          </div>

When the state is true, it also displays a '-' in place of where the '+' was until clicked again to set to false (hide the answer).

Thanks in advance!

Solution

In that situation, you need to handle the open/close trigger for every question.
So you need an additional variable in the object that corresponds for a single question if it’s open or not (by default it will be false), that way you can handle every single question itself instead of one single open state that can tell if to open or close all.
Moreover, I would suggest creating a component for a single question, and the component will receive props (isOpen, answer, question, etc..) inside the map function you will render for every item of the component.
for example :
<SingleQuestion question={item.question} answer={item.answer} isOpen={item.isOpen}>
You can let the component itself (SingleComponent) handle the inner state that decides isOpen true or false, that way every question will hold a state that lets show/hide the answer for the relevant question.

Hope you got the point, if not I’ll try to explain more if needed.

Answered By – LironShirazi

Answer Checked By – Clifford M. (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *