反应 setState/getState 和异步

新手上路,请多包涵

为什么 React 中没有异步 getState 函数?

文档告诉我们 setState 是异步的。很好,但这意味着 我们不能安全地使用 this.state 并且我们还需要一个异步 getState 来尊重执行顺序。

据我了解,我们永远不应该使用 this.state 并使用这样的 getState 函数:

   getState(callback) {
    this.setState((prevState) => {
      callback(prevState) ;
    });
  }
  ...
  this.getState((curState) => {
    // we now can use the current state safely
  }

我的思维方式在这里遗漏了什么?为什么 React 中不存在这样的功能?

- 编辑 -

正如我的一个朋友告诉我的那样,这并不清楚,因为我不相信但第一个答案,让我们分析一些代码:

 simpleFunc() {
    setState({ "counter" : 1 });
    setState({ "counter" : 2 });
    this.state.counter // => no garanty about the value
    getState((curState) => {  // ensure curState.counter is 2 });
}

这个简单的例子表明 我们不能在所有情况下都直接使用 this.state, 因为 setState 是异步的。

这是一个可以使用 getState 的反例: http ://codepen.io/Epithor/pen/ZLavWR?editors=0010#0

简短的回答: 不好的做法,甚至不确定 getState 给我们当前

解决方法很简单,但是我们可以分解一些函数并在不关心上下文的情况下使用它们这一事实似乎很有趣,不是吗?

因此,当许多事件以特定顺序发生时,一些事件会更改状态,一些会读取状态:您如何确定,当一个事件读取状态时,使用 this.state 读取良好状态,因为所有更改都是异步的?

事实上,一切都是关于时间的:

 T     : event 1, change state
T+1ms : event 2, change state
T+2ms : event 3, read state
T+3ms : event 4, change state

由于您无法预测事件 1 或 2 的 setState 究竟何时会发生, 您如何保证事件 3 将真正读取事件 2 中设置的状态?

简短的回答: 事件在 JS 堆栈中排队,而状态更改在内部 React 队列中排队。在伸出手之前,内部 React 队列已完全取消堆叠。

原文由 user2668735 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 487
2 个回答

一般来说, 您绝对可以直接使用 this.state 。你不应该直接 改变 状态( this.state.foo = 0 ),而是在你想改变状态时使用 setState

通常一个 setState 看起来像这样:

 this.setState({
    foo: 0
})

然后您可以安全地使用 this.state.foo 例如在您的 render() 函数中。

但是有一点需要注意,由于 setState 的异步性质,您无法保证在 this.state setState .

 myFunc(baz) {
    this.setState({
        foo: baz + 1
    })
    console.log(this.state.foo) // not guaranteed
}

最好做

myFunc(baz) {
    const bazOne = baz + 1
    this.setState({
        foo: bazOne
    })
    console.log(bazOne)
}

或者使用 setState 函数的第二个参数,用作 setState 操作完成时执行的回调。在该回调中,您将可以访问更新的状态,即 this.state

 myFunc(baz) {
    this.setState({ foo: baz + 1 }, () => {
        console.log(this.state.foo) // guaranteed in callback
    });
}

见: https ://facebook.github.io/react/docs/react-component.html#setstate

原文由 inostia 发布,翻译遵循 CC BY-SA 4.0 许可协议

它实际上不是错误/问题,而是架构决定: state 不打算用作简单的属性/变量/存储,它专门用于界面/视觉状态,并且,作为这样,不需要在每次调用时都更新。它使用一个内部队列,所以如果你在渲染之前多次交换状态,它实际上只会用最终值更新一次,并且在调用 render 方法时,它将包含正确的值。

如果您只需要在执行期间或在同一阶段运行的方法之间存储/检索信息(例如 componentWillReceivePropsshouldComponentUpdate ),您可以安全地使用 this.anyProperty 一如既往:

 componentWillReceiveProps() {
  this.value = 'guaranteed';
  return true;
}
shouldComponentUpdate() {
  if (this.value === 'guaranteed') {
    console.log('will always return true');
  }
}
componentDidUpdate() {
  this.value = ''; //cleanup
}

在上面的示例中,如果您使用“setState”,则无法保证该值始终会在“shouldComponentUpdate”中更新,但如果您将其用于预期目的,则无关紧要。状态更改保证在 render 时间之前被刷新,因此它应该只包含在渲染阶段使用的信息,而不是对象的事务/内部数据。您可以像往常一样自由地继续使用对象属性。

原文由 diego nunes 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进