如何确保我正在阅读最新版本的状态?



我可能错过了一些东西。我知道setStateReact 中是异步的,但我似乎仍然有这个问题。

想象一下,当用户单击我的应用程序上的任何按钮时,下面是一个处理程序

1. ButtonHandler()
2. {
3. if(!this.state.flag)
4. {
5.   alert("flag is false");
6. }
7. this.setState({flag:true});
8. 
9. }
  • 现在想象一下,用户非常快速地单击第一个按钮,然后单击第二个按钮。
  • 想象一下,第一次调用处理程序this.setState({flag:true})执行时,但是当第二次调用处理程序时,尚未反映上一次调用的状态更改- 并且this.state.flag返回false
  • 这种情况会发生吗(甚至在理论上)? 有哪些方法可以确保我阅读最新的状态?
  • 我知道setState(function(prevState, props){..})可以让您访问以前的状态,但是如果我只想像第 3 行那样读取状态而不设置它怎么办?

正如您正确指出的,要根据以前的状态设置状态,您需要使用函数重载。

我知道setState(function(prevState, props){..})让你访问以前的状态

所以你的例子看起来像这样:

handleClick() {
this.setState(prevState => {
return {
flag: !prevState.flag
};
});
}

如果我只想像第 3 行一样读取状态而不设置它怎么办?

让我们回过头来思考为什么要这样做。

如果要执行副作用(例如.log,控制台或启动 AJAX 请求),那么正确的位置是componentDidUpdate生命周期方法。它还允许您访问以前的状态:

componentDidUpdate(prevState) {
if (!prevState.flag && this.state.flag) {
alert('flag has changed from false to true!');
}
if (prevState.flag && !this.state.flag) {
alert('flag has changed from true to false!');
}    
}

这是使用 React 状态的预期方式。你让 React 管理状态,而不用担心它何时被设置。如果要根据以前的状态设置状态,请将函数传递给setState。如果要根据状态更改执行副作用,请在componentDidUpdate中比较以前和当前状态。

当然,作为最后的手段,您可以使实例变量独立于状态。

React 的哲学

状态和 props 应指示组件渲染所需的内容。每当状态和道具发生变化时,都会调用 React 的渲染。

副作用

在您的情况下,您正在根据需要特定时间的用户交互引起副作用。在我看来,一旦你退出渲染 - 你可能想要重新考虑stateprops,并坚持使用无论如何都是同步的常规实例属性。

解决真正的问题 - 在 React 之外

只需将this.state.flag更改为随处this.flag,并使用分配而不是setState更新它。这样你

如果您仍然必须使用 .state

你可以绕过这个,丑陋的。我为此编写了代码,但我宁愿不在这里发布它,这样人们就不会使用它:)

  • 首先承诺。
  • 然后使用实用程序只关心函数调用中解析的最后一个承诺。这是一个示例库,但实际代码是~10LoC,无论如何都很简单。
  • 现在,一个带有last调用的 promisized setState 为您提供了您正在寻找的保证。

以下是使用此类代码的方式:

explicitlyNotShown({x: 5}).then(() => {
// we are guaranteed that this call and any other setState calls are done here. 
});

(注意:对于 MobX,这不是问题,因为状态更新是同步的)。

相关内容

最新更新