Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Toggle Hook State

I tried to toggle individual item but unfortunately whenever I try to toggle an item the other item gets affected. Here is my code:

const FAQ = () => {
  const [open, setOpen] = useState(false);
  const [data, setData] = useState(faqData);
  return (
    <FAQSection>
      <FAQTitle>Frequently Asked Questions</FAQTitle>

      <Questions>
        <QuestionItemDetail>
          {data.map((item) => {
            const { id, question, answer } = item;

            return (
              <div key={id}>
                <QuestionItem onClick={() => setOpen(!open)}>
                  <QuestionItemTitle>{question}</QuestionItemTitle>
                  {open ? <Close /> : <Add />}
                </QuestionItem>
                <ReadQuestion>
                  {open && (
                    <ReadQuestionDetail>
                      <ReadQuestionDesc>{answer}</ReadQuestionDesc>
                    </ReadQuestionDetail>
                  )}
                </ReadQuestion>
              </div>
            );
          })}
        </QuestionItemDetail>
      </Questions>
    </FAQSection>
  );
};

What might be wrong with this because I ensured the dummy data has a unique ID.

like image 286
Oge Obubu Avatar asked Jan 18 '26 12:01

Oge Obubu


2 Answers

Because you use a boolean to control all open/close. You need to use index/id to control this.

const [open, setOpen] = useState(null);
...
onClick={() => setOpen(preOpen => preOpen === id ? null : id)}
...
{open === id && (<ReadQuestionDetail>...</ReadQuestionDetail>)}
like image 70
Viet Avatar answered Jan 20 '26 02:01

Viet


Your open state is used for all of the items in your data array, which is why it affects all of the items when toggled.

I recommend:

  1. putting all of the data item html/jsx inside a new component.
  2. Inside this new component, create an open state like so:
const MyItemComponent = (id, question, answer) => {
  const [open, setOpen] = useState(false);
  return (
    <div key={id}>
      <QuestionItem onClick={() => setOpen(!open)}>
        <QuestionItemTitle>{question}</QuestionItemTitle>
        {open ? <Close /> : <Add />}
      </QuestionItem>
      <ReadQuestion>
        {open && (
          <ReadQuestionDetail>
            <ReadQuestionDesc>{answer}</ReadQuestionDesc>
          </ReadQuestionDetail>
        )}
      </ReadQuestion>
    </div>
  );
}

const FAQ = () => {
  const [data, setData] = useState(faqData);
  return (
    <FAQSection>
      <FAQTitle>Frequently Asked Questions</FAQTitle>

      <Questions>
        <QuestionItemDetail>
          {data.map((item) => {
            const { id, question, answer } = item;

            return (
              <MyItemComponent id={id} question={question} answer={answer} />
            );
          })}
        </QuestionItemDetail>
      </Questions>
    </FAQSection>
  );
};

This will give you an individual open state for each item.

like image 35
charlieb Avatar answered Jan 20 '26 01:01

charlieb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!