React setState()保证

时间:2017-03-27 15:33:33

标签: javascript reactjs

在setState的文档中,可以这样说:

  

setState()不会立即改变this.state,但会创建挂起状态转换。在调用此方法后访问this.state可能会返回现有值。

     

无法保证对setState的调用进行同步操作,并且可以对调用进行批处理以获得性能提升。

所以我理解你是否有像这样的事件处理程序:

handleClick() {
  this.stuff1();
  this.stuff2();
}

stuff1() {
  this.setState({...});
}

stuff2() {
  doSomethingWithState(this.state);
  this.setState({...});
}

然后在stuff2方法中你可能没有(或者这保证你赢了......)从stuff1看到状态更新。 React提供了一种安全的方式。通过向setState()而不是对象提供函数来访问先前的状态。但是大概你可以通过在处理事件时自己跟踪状态并在方法结束时调用setState()一次来解决这个问题。所以也许有另一个原因选择为setState()提供一个函数。如果在调用handleClick方法之前对状态的其他更改进行了批处理,该怎么办?

例如,如果handleClick()被调用两次,那么我保证在第二次调用handleClick()时第一次调用handleClick()时会看到状态更改吗?还是有其他方式在调用事件处理程序之前状态可能变脏?

3 个答案:

答案 0 :(得分:2)

如果你没有使用回调函数而不是传入一个对象,那么只要你有一个从前一个状态派生的状态,就会遇到一个不同步的问题。在您的上一个示例中,只有使用该函数才能保证。如果您依赖于this.state,您可能很容易遇到一次调用handleClick的情况,状态转换排队等待稍后解决,您再次调用handleClick并且第一个状态更改仍处于待处理状态且处于队列状态,因此当您调用this.state时,它将具有与第一个handleClick相同的状态,这可能不是您想要的。

这将是使用回调函数的一个示例,假设doSomethingWithState返回更新的状态对象并且当然不是变异的。

stuff2() {
  this.setState((state) => {
    const updatedState = doSomethingWithState(state);
    return state;
  })
}

这是关于使用函数vs setState的一篇很棒的文章,还包括一个演示问题的codepen示例。 https://medium.com/@shopsifter/using-a-function-in-setstate-instead-of-an-object-1f5cfd6e55d1#.gm2t01g70

答案 1 :(得分:1)

如果我理解你是对的,那么答案是否定的,你不能保证,因为setState是一个异步操作 - 所以它有点像你提到的第一个'问题'。您可以为setState方法提供回调函数,该函数将在setState方法完成时触发。然后,在回调范围内,您可以保证更新当前状态并提供旧状态以进行比较和其他内容....

答案 2 :(得分:0)

您可以按照所述提供回调。或者,由于您希望第一个函数在handleClick()中执行,因此您可以在设置第一个函数的状态后调用第二个函数。即

handleClick() {
  this.stuff1();
}

stuff1() {
  this.setState({...}, 
    () => { 
      this.stuff2(); 
    });
}

stuff2() {
  doSomethingWithState(this.state);
  this.setState({...});
}

我认为这将为提出的问题提供解决方案。由于我们不能保证对 setState 的调用的同步操作,因为它是异步操作。