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

React setState Not Waiting Even With Proper Format

这是在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.超时前TOKEN:0
3.超时后TOKEN:0。

我不想将 //rest of my function 放在回调中,因为它是一个很长的函数。制作函数 "async" 并在 this.setState 前面添加 await 是可行的,但不建议在各种来源上使用。

为什么我的代码不起作用?如何在超时前调用 TOKEN 之前完成 setState 调用,而无需大量更改我的代码?

谢谢。

提供回调函数不会导致 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
    });

I don't want to put the //rest of my function in the callback because it's a pretty long 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
  }
}

Making the function "async" and prepending this.setState with await works, but is not recommended on various sources.

不推荐的原因是它依赖于反应的实现细节。他们碰巧以这样一种方式实现 setState 的批处理,如果你排队一个微任务,你将等待足够长的时间让反应完成它的工作。但是 React 并不能保证这就是他们实现它的方式。

来自文档

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.

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

设置您的状态