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

时间:2017-04-14 23:38:51

标签: javascript reactjs

我可能会遗漏一些东西。我知道setState在React中是异步的,但我似乎仍有这个问题。

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

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行的状态并且未设置它,该怎么办?

2 个答案:

答案 0 :(得分:3)

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

  

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

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

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

如果我只想阅读第3行的状态而不设置它会怎么样?

让我们回想一下为什么你想要这样做。

如果您想执行副作用(例如,登录到控制台或启动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中的上一个和当前状态。

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

答案 1 :(得分:1)

React的理念

state和props应该指示组件渲染所需的东西。只要状态和道具发生变化,就会调用React的渲染。

副作用

在您的情况下,您会根据需要特定时间的用户互动造成副作用。在我看来,一旦你退出渲染 - 你可能想重新考虑stateprops并坚持一个同步的常规实例属性。

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

只需将this.state.flag更改为this.flag,然后使用分配而不是setState进行更新。那样你

如果您仍 使用.state

你可以解决这个问题。我为此编写了代码,但我宁愿不在这里发布,所以人们不会使用它:)

  • 首先promisify
  • 然后使用实用程序仅关注在函数调用中解析的最后一个promise。 Here is an example library但是实际代码大约是10LoC并且很简单。
  • 现在,调用了last的promisified setState可以为您提供所需的保证。

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

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

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