Home > Software engineering >  Applying state change to specific index of an array in React
Applying state change to specific index of an array in React

Time:12-22

Yo there! Back at it again with a noob question!

So I'm fetching data from an API to render a quizz app and I'm struggling with a simple(I think) function : I have an array containing 4 answers. This array renders 4 divs (so my answers can each have an individual div). I'd like to change the color of the clicked div so I can verify if the clicked div is the good answer later on.

Problem is when I click, the whole array of answers (the 4 divs) are all changing color.

How can I achieve that?

I've done something like that to the divs I'm rendering :

const [on, setOn] = React.useState(false);

  function toggle() {
    setOn((prevOn) => !prevOn);
  }

  const styles = {
    backgroundColor: on ? "#D6DBF5" : "transparent",
  };

I'll provide the whole code of the component and the API link I'm using at the end of the post so if needed you can see how I render the whole thing.

Maybe it's cause the API lacks an "on" value for its objects? I've tried to assign a boolean value to each of the items but I couldn't seem to make it work.

Thanks in advance for your help!

The whole component :

import React from "react";
import { useRef } from "react";

export default function Quizz(props) {
  const [on, setOn] = React.useState(false);

  function toggle() {
    setOn((prevOn) => !prevOn);
  }

  const styles = {
    backgroundColor: on ? "#D6DBF5" : "transparent",
  };

  function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      let j = Math.floor(Math.random() * (i   1));
      let temp = array[i];
      array[i] = array[j];
      array[j] = temp;
    }
    return array;
  }

  let answers = props.incorrect_answers;

  const ref = useRef(false);
  if (!ref.current) {
    answers.push(props.correct_answer);

    shuffleArray(answers);
    ref.current = true;
  }

  const cards = answers.map((answer, key) => (
    <div key={key} className="individuals" onClick={toggle} style={styles}>
      {answer}
    </div>
  ));

  console.log(answers);
  console.log(props.correct_answer);

  return (
    <div className="questions">
      <div>
        <h2>{props.question}</h2>
      </div>
      <div className="individuals__container">{cards}</div>
      <hr />
    </div>
  );
}

The API link I'm using : "https://opentdb.com/api.php?amount=5&category=27&type=multiple"

CodePudding user response:

Since your answers are unique in every quizz, you can use them as id, and instead of keeping a boolean value in the state, you can keep the selected answer in the state, and when you want render your JSX you can check the state is the same as current answer or not, if yes then you can change it's background like this:

function Quizz(props) {
  const [activeAnswer, setActiveAnswer] = React.useState('');
  function toggle(answer) {
    setActiveAnswer(answer);
  }
  ...
  const cards = answers.map((answer, key) => (
    <div key={key}
         className="individuals"
         onClick={()=> toggle(answer)}
         style={{background: answer == activeAnswer ? "#D6DBF5" : "transparent" }}>
         {answer}
    </div>
));
  ...
}
  • Related