首页 > 解决方案 > setState 在此代码中的工作方式的混乱

问题描述

我是 React 的新手,正在学习 setState 的工作原理。所以,你可以看到下面的代码:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.handleReset = this.handleReset.bind(this);
    this.state = {
      count: 5
    };
  }

 handleReset() {
    this.setState({count:0})

this.setState({count:this.state.count+1})

}
render() {
    return (
      <div>
        <button onClick={this.handleReset}>reset</button>
      </div>
    );
  }

因此,我对上述代码的期望是,当我单击按钮时,它不会输出 1,而是将 1 添加到当前计数状态并显示 6。这就是我假设两个 setStates 在 handleReset 方法中工作的方式。我不知道为什么它呈现 6 而不是 1

标签: javascriptreactjs

解决方案


正如 Rikin 解释的那样,setState将它们批处理在一起,只执行最后一个......是setState的,它是异步的,并且确实需要回调,所以如果你想要你的预期结果,你可以这样做:

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 5 };
    this.handleReset = this.handleReset.bind(this);
  }

  handleReset() {
    this.setState({ count: 0 }, 
    /* here is you callback */
    () => this.setState({ count: this.state.count + 1 }))
  }

  render() {
    return (
      <div>
        <div>{this.state.count}</div>
        <button onClick={this.handleReset}>reset</button>
      </div>
    );
  }
}

希望它有所帮助......这是一个现场演示:https ://stackblitz.com/edit/react-dbc11s

setState调用被批处理在一起,因此只有最后一个进行更新。为了解释这种情况,让我们使用 OP 的示例和一些更类似的硬编码更新:

handleReset() {
  this.setState({ count: 0 })
  this.setState({ count: 10 })
  this.setState({ count: 100 })
  this.setState({ count: this.state.count + 1 })
}

引擎盖下发生的事情是您可以将其视为:

Object.assign(
  previousState, // { count: 5 }
  {count: 0}, //  { count: 0 }
  {count: 10}, //  { count: 10 }
  {count: 100}, //  { count: 100 }
  {count: state.count + 1} // { count: 5 + 1}
)

Object.assign 覆盖的值,count因此只有最后一个值才能进行最终更新,这恰好是6

如果要使用先前状态的值,则必须依赖在setState执行时使用现有状态值的函数方法,然后对其执行更新操作。

两种场景都在这里演示:https ://codesandbox.io/s/musing-rhodes-jsf6b


推荐阅读