为什么在React的#setState中使用函数解决了异步问题?

sta*_*lei 9 javascript reactjs

文档中,它说"React可以将多个setState()调用批处理为单个性能更新",因此它建议使用函数而不是对象作为setState参数.这是如何解决问题的?

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
Run Code Online (Sandbox Code Playgroud)

fin*_*req 6

当你将一个对象传递给setState时,react将接受你传入的任何内容,创建一个事件来跟踪传入的内容,然后最终更新状态.正如文档所说,如果运行多个setStates,react可以将它们一起批处理,因为它将异步发生,也就是在某些时候,当你运行第一个例子时,它可能会使用一个this.state.counter实际上是旧的并导致意外的一面效果.

第二个选项被认为更安全,因为它很像一个promise:当你传入一个函数时,React只会在状态实际更新后运行此函数.这可以确保this.state.counter每次更新时都有正确的变量,方法是使用prevState它们提供的变量作为回调的参数.

我没有使用第一种方法遇到问题,但我也没有尝试过立即淹没一堆setStates调用,我确信这是什么时候出现的.我看到这种犯规的主要方式是他们在设置状态后尝试使用新状态.

例如:

increaseCounter() {
 this.setState({
   counter: this.state.counter + this.props.increment,
 });

 // this will more then likely be the previous value 
 // as setState does not run right away, but asynchronously 
 this.useNewCounter(this.state.counter) 
}
Run Code Online (Sandbox Code Playgroud)

在该示例中,人们可能期望在useNewCounter调用时它将使用最新状态,但它不会,引用仍将指向前一个值,直到反应更新状态,该状态将在此方法被调用之后的某个时刻.