'Toggle class on a mapped element in react

I am learning react and I have some doubts about changing the color onClick How can I toggle the className of a <p> element that is being clicked? At the moment clicking on one changes the color on everything.

I have read about passing a state on a parent element but at this point is getting a bit confusing and if someone could help me clarifying this would be nice.

Here's the code of my child element:

import "./Answer.scss";

function Answer(props) {
  const getAnswers = [];
  const correct_answer = props.correct_answer;
  getAnswers.push(correct_answer);

  for (let i = 0; i < props.incorrect_answers.length; i++) {
    getAnswers.push(props.incorrect_answers[i]);
  }

  const [answers, setAnswer] = useState(getAnswers);
  const [active, setActive] = useState(true);

  const displayAnswers = answers.map((answer, index) => (
    <p
      className={active ? "answer" : "answer-active"}
      key={index}
      onClick={() => setActive((prevState) => !prevState)}
    >
      {answer.replace(/&quot;|&#039;/g, '"')}
    </p>
  ));

  return <div className="answer-box">{displayAnswers}</div>;
}

export default Answer;

And this is the parent:

import Answer from "../Answer/Answer";

function Questions(props) {
  const questions = props.questions.map((question, index) => {
    return (
      <div className="question" key={index}>
        <h2>{question.question.replace(/&quot;|&#039;/g, '"')}</h2>
        <Answer
          incorrect_answers={question.incorrect_answers}
          correct_answer={question.correct_answer}
        />
        <hr></hr>
      </div>
    );
  });

  return <div className="questions-container">{questions}</div>;
}

export default Questions;

Thanks everyone



Solution 1:[1]

Check this code.

const [answers, setAnswer] = useState(getAnswers);
const [active, setActive] = useState(true);

const displayAnswers = answers.map((answer, index) => (
  <p
    className={active ? "answer" : "answer-active"}
    key={index}
    onClick={() => setActive((prevState) => !prevState)}
  >
    {answer.replace(/&quot;|&#039;/g, '"')}
  </p>
));

You are iterating your answers and updating the same state variable for each answer. It's like you are over-writing the updated values. Instead, you can make a separate state variable for each and every option. Based on the onClick, you can update that specific answer state and use it in the code. Check the below code.

const AnswerText = ({ valid, index, answer }) => {
  const [active, setActive] = useState(valid);
  return (
    <p
      className={active ? "answer" : "answer-active"}
      key={index}
      onClick={() => setActive((prevState) => !prevState)}
    >
      {answer}
    </p>
  );
};

You can use the above component in the map and display your answers.

Attached is a sandbox for reference.

Edit reverent-glitter-d9yxce

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 mchowdam