React setState即使使用正确的格式也不会等待

时间:2019-07-16 16:21:41

标签: javascript reactjs react-native asynchronous setstate

这是在React:中调用setState的推荐方法

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

但是,在转到此代码的下一行之前,此格式仍然不等待setState完成:

  pressed = () => {
    this.setState((prevState, props) => ({
      token: 1
    }), () => console.warn("TOKEN setState Callback: " + this.state.token));
    console.warn("TOKEN before timeout: " + this.state.token);
    setTimeout(function() {console.warn("TOKEN after timeout: " + this.state.token)}.bind(this), 500);
    ...
    //rest of function
  }

在这种情况下,这是输出的顺序
1. TOKEN setState回调:1
2.超时前的令牌:0
3.超时后的令牌:0。

我不想将//rest of my function放在回调中,因为它是一个相当长的函数。使函数“异步”并在this.setState之前加上await是可行的,但是不建议在各种来源上使用。

为什么我的代码不起作用?如何在超时之前调用TOKEN之前使setState调用完成,而又不改变代码的范围?

谢谢。

2 个答案:

答案 0 :(得分:4)

提供回调函数不会导致setState变为同步。相反,您应该将代码放入回调函数中,并在完成设置状态后将调用它。

    this.setState((prevState, props) => ({
      token: 1
    }), () => {
      console.warn("TOKEN setState Callback: " + this.state.token);
      console.warn("TOKEN before timeout: " + this.state.token);
      setTimeout(function() {console.warn("TOKEN after timeout: " + this.state.token)}.bind(this), 500);
      //rest of function
    });
  

我不想将//函数的其余部分放在回调中,因为这是一个相当长的函数。

如果希望代码在设置状态之后运行,则将其放入回调中。您可以将其提取到帮助程序方法中,以使其更易于阅读,但是代码的长度不会改变您需要调用的位置。

您的另一个选择是将代码放入componentDidUpdate中,并将其包装在检查令牌中的代码是否已更改:

componentDidUpdate(prevProps, prevState) {
  if (prevState.token !== this.state.token) {
      console.warn("TOKEN before timeout: " + this.state.token);
      setTimeout(function() {console.warn("TOKEN after timeout: " + this.state.token)}.bind(this), 500);
      //rest of function
  }
}
  

使函数“异步”并在a.wait之前添加this.setState是可行的,但不建议在各种来源上使用。

不推荐的原因是它依赖于react的实现细节。他们碰巧以如下方式实现setState的批处理:如果您将微任务排队,您将等待足够长的时间来做出反应以完成其工作。但是react无法保证这就是他们实现它的方式。

答案 1 :(得分:1)

从文档中

  

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

因此,即使您已运行setState,也不会自动更新令牌以供您在函数中使用新值。如果令牌仅在该令牌内部使用,那么我将在其中设置变量以增加令牌并在函数内部专门使用它,然后最后使用this.setState({token: 1})

设置状态