【问题标题】:Why does state not update as expected?为什么状态没有按预期更新?
【发布时间】:2019-03-21 03:28:29
【问题描述】:

我目前正在构建一个井字游戏,并希望将当前玩家的状态存储为 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)
}

任何帮助弄清楚如何让这个函数返回更新的状态值会很棒!

【问题讨论】:

  • 向我们展示 this.setState()
  • @user5328504 在第 13 行。
  • setState() 是一个函数....该函数是在您提供的代码中定义的
  • 我明白了...没有阅读反应标签...删除了我的答案!
  • @user5328504 np,伙计。感谢您的努力!

标签: javascript reactjs tic-tac-toe setstate


【解决方案1】:

状态更改为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);

【讨论】:

  • 你是救生员。这非常有效。我将不得不阅读异步性以更好地了解到底发生了什么,但是伙计,这真的很有帮助。谢谢!
【解决方案2】:

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

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

setState(反应文档):

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

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

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

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


更新:这个答案最初错误地指出setState 返回了一个承诺,并建议您可以链接.then(),一旦状态更新就会被调用。此后,我从@Sushanthanswer 获得灵感,更正了答案。

【讨论】:

  • 记录仅用于演示目的。在我的源代码中,我调用了一个函数来检查获胜条件。我认为即使我将 console.log 替换为函数调用,您的建议也会起作用?
  • 也许我做错了什么,但在尝试此操作时出现“未捕获的类型错误:无法读取未定义的属性'then'”。
  • 尽管 setState 是异步的,但它 - 违反直觉 - 不会返回承诺,因此 .then 将不起作用。你必须给它一个函数的第二个参数才能在它完成后执行。 this.setState({}, () => console.log(this.state));
  • @Mark 这正是 Sushanth 所说的。所以,也给你点!谢谢!
  • 很抱歉在这里带你走错路。为了后代,我已经更正了我的答案。
【解决方案3】:

状态更改为asynchronous。所以用一个函数代替setState函数的第二个参数你可以调用回调函数到console或其他的事情。

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

【讨论】:

    猜你喜欢
    • 2020-01-25
    • 2021-08-04
    • 1970-01-01
    • 2021-06-07
    • 2017-01-25
    • 2022-01-16
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多