Gabriel Nicolitoiu
Gabriel Nicolitoiu

Reputation: 15

How can I setState multiple times in one function?

So i'm trying to make a card guessing game and I need to set state multiple times in one clickHandler, but everytime it just uses the previous state because state is asynchronous and it doesn't have enough time to update. How can I achieve something similar to async await in this event handler? SetGame is my setState.

const clickHandler = (e) => {
  let copy = [...game.pictures];
  shuffle(copy);
  setGame((prevState) => {
    return { ...prevState, pictures: copy };
  });

  let clickedId = [...game.clickedPics];

  if (!clickedId.includes(e.target.id)) {
    setGame((prevState) => {
      return { ...prevState, currentScore: game.currentScore + 1 };
    });

    if (game.highScore < game.currentScore) {
      setGame((prevState) => {
        return { ...prevState, highScore: game.currentScore };
      });
    }

    clickedId.push(e.target.id);
    setGame((prevState) => {
      return { ...prevState, clickedPics: clickedId };
    });
    console.log(game.clickedPics);
  } else {
    setGame((prevState) => {
      return { ...prevState, currentScore: 0 };
    });
    clickedId = [];
    setGame((prevState) => {
      return { ...prevState, clickedPics: clickedId };
    });
  }
};

Upvotes: 1

Views: 36

Answers (1)

Sagi Rika
Sagi Rika

Reputation: 2979

Since, as you said, setState is an async operation, you have to create your state object and only setGame once in the end. Try this:

  let copy = [...game.pictures];
  const stateCopy = { ...game } // or whatever name your state is here
  shuffle(copy);
  stateCopy.pictures = copy;

  let clickedId = [...game.clickedPics];

  if (!clickedId.includes(e.target.id)) {
    stateCopy.currentScore = game.currentScore + 1;

    if (game.highScore < game.currentScore) {
      stateCopy.highScore = game.currentScore;
    }

    clickedId.push(e.target.id);
    stateCopy.clickedPics = clickedId;
    console.log(game.clickedPics);
  } else {
    stateCopy.currentScore = 0;
    clickedId = [];
    stateCopy.clickedPics = clickedId;
  }

  setGame(stateCopy);
};

Upvotes: 2

Related Questions