Home > Mobile >  React setState and use the value to update another state
React setState and use the value to update another state

Time:12-13

I have a simple roll the dice code and I want to update the score based on the dice roll.

This is the states of the dices and the scores:

 const [Dice1, setDice1] = useState(0);
 const [Dice2, setDice2] = useState(0);

 const [Score1, setScore1] = useState(0);
 const [Score2, setScore2] = useState(0);

 function randomNum() {
      setDice2(Math.floor(Math.random() * 6)   1);
      setDice1(Math.floor(Math.random() * 6)   1);
      Dice1 > Dice2 && Dice1 !== Dice2 ? setScore1(Score1   1) : Dice2 > Dice1 && Dice1 !== Dice2 ? setScore2(Score2   1) : setScore2(Score2   0);
 }

The function randomNum is triggered on click.

 return (
      <div className="App">
           <header className="App-header">
                <p>Player 1 rolls {Dice1}</p>
                <p>Player 2 rolls {Dice2}</p>
                <button onClick={randomNum}>Roll the dice</button>
                {Dice1 > Dice2 ? <p>Player 1 win</p> : Dice1 === Dice2 ? <p>Draw</p> : <p>Player 2 win</p>}
                <p>Player 1 score is {Score1} points</p>
                <p>Player 2 score is {Score2} points</p>
                <button onClick={resetScore}>Reset score</button>
           </header>
      </div>
 );

Everything works well, except that the score if updated with 1 round lag. Everytime I roll, it is added the point from the last round. What am I'm doing wrong here?

enter image description here

CodePudding user response:

Update

One Score state would look like

  const [score, setScore] = useState({
    score1: 0,
    score2: 0
  });

You can update like

  setScore(prev=>{...prev, score1: prev.score1   1})
setScore(prev=>{...prev, score2: prev.score2   1})


Try this

  1. Use one state for dice instead
const [dice, setDice] = useState({
    dice1: 0,
    dice2: 0,
  })

  1. Update the state
function randomNum() {
    const dice1Val = Math.floor(Math.random() * 6)   1;
    const dice2val = Math.floor(Math.random() * 6)   1;
    setDice({
      dice1: dice1Val,
      dice2val: dice2Val
    })

  1. And since setting score is an effect of setting dice, update the score in a useEffect
useEffect(() => {
      dice.dice1 > dice.dice2 && dice.dice1 !== dice.dice2 ? setScore1(prev => prev   1); : dice.dice2 > dice.dice1 && dice.dice1 !== dice.dice2 ? setScore2(prev => prev   1) : setScore2(prev => prev   1)
    },[dice])
 }

You can also put the scores under one state instead.

CodePudding user response:

The most easiest way I can think of is to implement the resetScore function that will set the both states to 0.

function resetScore() { setScore1(0); setScore2(0); }

or call this function at the start of the randomNum.

CodePudding user response:

You are not using the previous state values correctly. It is not recommended to use previous state values directly while updating state variables.

So in your code instead of :

setScore1(Score1   1)

you should do like this :

setScore1(prevScore => prevScore   1);

and similarly for other state variables.

  • Related