简体   繁体   中英

React hooks - setState does not update some state properties

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 在此处输入图像描述

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;

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.

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM