【问题标题】:React setState Not Waiting Even With Proper Format即使使用正确的格式,React setState 也不会等待
【发布时间】:2019-07-16 16:21:41
【问题描述】:

这是在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 放在回调中,因为它是一个相当长的函数。使函数“异步”并在 this.setState 前面加上 await 可以工作,但不建议在各种来源上使用。

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

谢谢。

【问题讨论】:

  • 创建一个函数并在设置状态回调中调用它
  • 或者使用componentDidUpdate至于Why doesn't my code work?,因为setState()是异步的。另外,为什么不想将函数的其余部分移到回调中呢?如果您的函数往往很长,您可能希望以不同的方式组织代码。

标签: javascript reactjs react-native asynchronous setstate


【解决方案1】:

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

我不想将函数的 //rest 放在回调中,因为它是一个相当长的函数。

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

您的另一个选择是将代码放入 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
  }
}

使函数“异步”并在 this.setState 前加上 await 可以工作,但不建议在各种来源上使用。

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

【讨论】:

    【解决方案2】:

    来自文档

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

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

    【讨论】:

      猜你喜欢
      • 2020-01-30
      • 2021-05-26
      • 2020-12-07
      • 2020-12-23
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多