Reactjs React setState/getState和asynchronous

Reactjs React setState/getState和asynchronous,reactjs,asynchronous,setstate,getstate,Reactjs,Asynchronous,Setstate,Getstate,为什么React中没有异步getState函数? 文档告诉我们setState是异步的。很好,但这意味着我们不能安全地使用这个.state,我们还需要一个异步getState来尊重执行顺序 据我所知,我们永远不应该使用this.state,而应该像这样使用getState函数: getState(callback) { this.setState((prevState) => { callback(prevState) ; }); } ... t

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

文档告诉我们setState是异步的。很好,但这意味着我们不能安全地使用这个.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的反例:

简短回答:糟糕的做法,甚至不确定getState是否给了我们当前

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

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

事实上,一切都与时间有关:

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


简短回答:事件在JS堆栈中排队,而状态更改在内部React队列中排队。在举手之前,内部反应队列已完全打开。

您完全可以使用
此选项。通常情况下,直接说明
。您不应该直接改变状态(
this.state.foo=0
),而应该在需要改变状态时使用
setState

通常,
setState
如下所示:

this.setState({
    foo: 0
})
然后可以在
render()函数中安全地使用
this.state.foo
eg

但是需要注意的是,由于
setState
的异步性质,您不能保证在调用
setState
后可以立即访问
此.state

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
functions第二个参数,该参数用作setState操作完成时执行的回调。在该回调中,您将有权访问更新的状态,即
this.state

this.setState({foo},()=>{console.log(this.state.foo)})


请参阅:

设置状态是异步的,因此您无法立即访问更改的属性,但是,在某些情况下,您希望在状态更改后执行操作,在这些情况下,您可以执行以下操作:

...

this.state = {
  x = 1
}

...

this.setState({
  x = 2
}, () => {
  console.log(this.state.x) // outputs 2
});

setState函数是在一个排队的勾号上调用的,因此您可以将x个setState排队,它们将在下一个勾号上执行。

这实际上不是一个bug/问题,而是一个架构决策:
状态
不打算用作简单的属性/变量/存储,它专门用于接口/可视状态,因此不需要在每次调用时更新。它使用一个内部队列,因此如果在渲染之前多次交换状态,它实际上只会使用最终值更新一次,并且在调用
render
方法时,它将包含正确的值

如果您只需要在执行期间或在同一阶段运行的方法之间存储/检索信息(
componentWillReceiveProps
shouldComponentUpdate
),您可以像往常一样安全地使用
此属性。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
时间之前刷新,因此它应该只包含在渲染阶段使用的信息,而不是对象的事务/内部数据。您可以像往常一样自由地继续使用对象属性。

“您绝对可以直接使用this.state”:根据我对React framework的了解,并非在所有情况下。我更新了我的帖子。啊,我明白你的意思。是的,没错。在这种情况下,您可以使用
setState
中的可选回调参数。但在这种情况下,我认为如果您需要在函数中访问变量,最好将
counter
存储到该变量中,因为正如您所说,您没有任何保证。我同意您的答案,但我仍然需要一个关于React/JS异步管理(队列等)的技术解释来深入理解:)@user2668735:JS有“完成“。事件被添加到队列中,并且仅在当前没有代码运行时进行处理。这意味着,如果您有一系列语句,那么这些语句都将在处理下一个事件之前执行。代码不会突然停止在函数的中间。换句话说,在您的示例中,您可以确定在访问
this.state.counter
时,状态尚未发生更改(假设状态是异步的)。看一看。我猜重新呈现DOM在计算上很昂贵,因此出于性能原因,需要等待队列清除后才能更新状态。如果没有足够的可用内存,同步
setState
可能会导致闪烁或其他显示问题。看这篇博文:在同一个刻度中设置和读取状态在我看来是相当不寻常的。我根本不是JS专家,你可能是对的。我认为这会将异步代码放在React async队列上,稍后执行,允许“unstack”以确保没有“wai”
componentWillReceiveProps() {
  this.value = 'guaranteed';
  return true;
}
shouldComponentUpdate() {
  if (this.value === 'guaranteed') {
    console.log('will always return true');
  }
}
componentDidUpdate() {
  this.value = ''; //cleanup
}