Reputation: 158
i am making a game but i am having a problem using setState hook on react, it isnt updating my state, my state properties are
const [state,setState] =useState({
score:0,
holes:9,
initGame:false,
lastHole:-1,
minPeepTime: 200,
maxPeepTime: 1000})
i also have 2 useEffect hook just for testing
useEffect(()=>{
console.log("init game");
console.log(state.initGame);
console.log("--------------");
},[state.initGame])
useEffect(()=>{
console.log("last hole");
console.log(state.lastHole);
console.log("##############");
},[state.lastHole])
and i have a function to start the game
const StartGame=()=>{
console.log("here")
setState({...state,initGame: true,score:0,lastHole: 15})
peep();
setTimeout(() => {
console.log("Game Over")
setState({...state,lastHole:-1,initGame: false})
}, 10000)
}
"here" is actually being printed, and when time is over "Game Over" is being printed. peep() function update the property lastHole and it call useEffect correctly, but property initGame is never being updated by setState and that my actual problem, useEffect for that property is never call (just the first time when my page is loaded, but not on StartGame function) and its value never change
UPD:
this is the peep function.
const randomTime = (min, max) => {
return Math.round(Math.random() * (max - min) + min);
};
const randomHole = () => {
const idx = Math.floor(Math.random() * state.holes);
if (idx === state.lastHole){
return randomHole();
}
setState({...state,lastHole: idx});
}
const peep = () => {
randomHole();
let time = randomTime(state.minPeepTime,state.maxPeepTime)
if(state.initGame){
setTimeout(() => {
peep()
}, time)
}
}
and this is the output of the code
Upvotes: 0
Views: 236
Reputation: 571
The problem here is with the setState. setState doesn't immediately change the state as you expect.
setState({
...state,
initGame: true,
score: 0,
lastHole: 15,
});
peep() // value of initGame is false
Unexpectedly, the value of initGame will still be false. Change all the setstates like given below.
setState((state) => ({
...state,
initGame: true,
score: 0,
lastHole: 15,
}));
This will successfully set initGame to true before calling peep()
The final output will be as shown below.
Upvotes: 0
Reputation: 984
To properly update state in this scenario use:
setState((initialState) => ({
...initialState,
initGame: true,
score: 0,
lastsHole: 15
}))
The setTimeout part becomes
setState((initialState) => ({
...initialState,
lastHole: -1,
initGame: false
}))
I don't know what peek does or the importance of the setTimeout though;
Upvotes: 1