为什么状态没有按预期更新?

时间:2019-03-21 03:28:29

标签: javascript reactjs tic-tac-toe setstate

我当前正在构建一个TicTacToe游戏,并希望将我当前的玩家存储为currentPlayer。一个玩家移动后,我将currentPlayer更新为另一玩家。但是,当我尝试将新状态记录到控制台时,它没有产生更新状态的值。

这是我的代码:

state = {
    currentPlayer: 'X',
}

// This function is triggered by an onClick attribute.
// It first finds the html element and renders the currentPlayer value from state.
// It then switchs the value of currentPlayer from X to O and calls setState to update the state.
// Why does the console.log not show the updated state value?

userDidMove = () => {
    document.getElementById('cell').innerHTML = this.state.currentPlayer
    let nextPlayer = this.state.currentPlayer === 'X' ? 'O' : 'X'
    this.setState({ 
        currentPlayer: nextPlayer,
    })
    console.log ('userDidMove changed state with ',this.state.currentPlayer)
}

任何帮助弄清楚如何获取此函数以返回更新后的状态值的帮助都将很棒!

3 个答案:

答案 0 :(得分:3)

状态更改为asynchronous。当您的新状态依赖于先前的状态时,请改用状态更新程序功能。

提交状态更改后,您可以使用将具有更新状态的回调。

this.setState((previousState) => {
  const nextPlayer = previousState.currentPlayer === 'X' ? 'O' : 'X';

  return {
    currentPlayer: nextPlayer
  }
}, () => {
  // your updated state related code here

  console.log('userDidMove changed state with ', this.state.currentPlayer)
});

this.setState(updatedFunc, callback);

答案 1 :(得分:1)

setState是异步的,因此状态不会立即更新。您可以将回调作为第二个参数传递给setState,只有在状态更新后才会调用该回调:

this.setState(
  { currentPlayer: nextPlayer },
  () => console.log(`userDidMove changed state with ${this.state.currentPlayer}`)
);

setState(React Docs):

  

setState(updater[, callback])setState(stateChange[, callback])

     

将setState()视为请求而不是立即命令   更新组件。为了获得更好的感知性能,React可能会   延迟它,然后在一次通过中更新几个组件。反应   不保证状态更改会立即应用。

     

setState()并不总是立即更新组件。它可能   批处理或将更新推迟到以后。这使得阅读this.state   在调用setState()之后立即发生潜在的陷阱。相反,使用   componentDidUpdate或setState回调(setState(updater,   回调)),保证在更新后都会触发   已应用。如果您需要根据之前的状态设置状态   状态,请阅读下面的updater参数。

注意:我建议您使用React Dev Tools观察状态,而不是记录状态。


更新:该答案最初错误地指出setState返回了诺言,并建议您可以链接.then(),一旦状态更新,该链接将被调用。此后,我根据@Sushanthanswer的启发,更正了答案。

答案 2 :(得分:0)

状态更改为asynchronous。因此请改用一个函数和setState函数的第二个参数,您可以将回调函数调用到console或进行其他操作。

this.setState(() => ({currentPlayer: nextPlayer}), () => {
  console.log('state', this.state.currentPlayer);
})