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?
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
- Use one state for dice instead
const [dice, setDice] = useState({
dice1: 0,
dice2: 0,
})
- 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
})
- 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.