Home > Back-end >  React state not available after using setState
React state not available after using setState

Time:08-29

I'm working on a trivia app using ReactjS and every time I try to update my state named "game", I get the following error message:

Uncaught TypeError: game is undefined.

My webapp is structured as follows: App -> Question -> Answers.

in App:

const [game, setGame] = React.useState([]);

function holdAnswer(qKey) {
  console.log(qKey);
  setGame((oldGame) => {
    oldGame.map((element) => {
      return qKey === element.key ? {} : element;
    });
  });
  console.log(qKey);
}

React.useEffect(function () {
  console.log("Effect ran");
  fetch("https://opentdb.com/api.php?amount=5")
    .then((res) => res.json())
    .then((data) =>
      setGame(
        data.results.map(function (element) {
          return {
            ...element,
            key: uniqid(),
            answers: arrayShuffle([
              ...element.incorrect_answers.map(
                (x) => new AnswerObj(x, false, uniqid())
              ),
              new AnswerObj(element.correct_answer, false, uniqid()),
            ]),
          };
        })
      )
    );
  console.log(game);
}, []);

var wholeQ = game.map((element) => {
  return (
    <Question wQ={element} holdAnswer={() => holdAnswer(element.key)} />
  );
});

in Question Component:

export default function Question(props) {
  const answers = arrayShuffle(props.wQ.answers).map((element) => {
    return <Answers wholeAnswer={element} holdAnswer={props.holdAnswer} />;
  });
  return (
    <div className="question">
      <p>{decode(props.wQ.question)}</p>
      <div className="answer-buttons-wrapper">{answers}</div>
    </div>
  );
}

in Answers Component:

export default function Answers(props) {
  return (
    <button className="answer-button" onClick={props.holdAnswer}>
      {decode(props.wholeAnswer.answer)}
    </button>
  );
}

CodePudding user response:

I believe the problem lies in the following block:

function holdAnswer(qKey) {
  console.log(qKey);
  setGame((oldGame) => {
    oldGame.map((element) => {
      return qKey === element.key ? {} : element;
    });
  });
  console.log(qKey);
}

As setGame ends up not returning anything and therefor sets the state with an undefined value.

To address this we can remove the curly-braces in setGame in-order to make it an "implicit return".
Alternatively, we can add a return statement before the mapping function.

// Either this ->

setGame((oldGame) =>
  oldGame.map((element) => {
    return qKey === element.key ? {} : element;
  });
);

// Or this ->

setGame((oldGame) => {
  return oldGame.map((element) => {
    return qKey === element.key ? {} : element;
  });
});
  • Related