为什么 setState 在 reactjAsync 中而不是 Sync 中?

我刚刚发现在反应 this.setState()函数在任何组件中都是异步的,或者在调用它的函数完成后被调用。

现在我搜索并找到了这个博客(SetState ()状态突变操作可能在 ReactJS 中是同步的)

在这里,他发现 setState是异步的(当栈为空时调用)或同步的(调用后立即调用) ,这取决于如何触发状态的变化。

这两样东西很难消化

  1. 在 blog 中,在函数 updateState内部调用 setState函数,但是触发 updateState函数的是被调用函数不知道的事情。
  2. 为什么他们要使 setState异步,因为 JS 是单线程语言,而 setState 不是 WebAPI 或服务器调用,所以只能在 JS 的线程上执行。他们这样做是为了重新呈现不停止所有事件侦听器和东西,或者有一些其他的设计问题。
165782 次浏览

1) setState操作是异步的,并且是为了性能提高而批处理的。

SetState ()不会立即变异 this.state,而是创建一个挂起的状态转换。在调用此方法后访问 this.state 可能会返回现有值。 不能保证调用 setState 的同步操作,为了提高性能,可能会对调用进行批处理。


2)为什么他们要使 setState 异步,因为 JS 是一个单线程语言,而这个 setState不是一个 WebAPI 或服务器调用?< br/>

这是因为 setState改变了状态并导致重新呈现。这可能是一个昂贵的操作,使其同步可能会使浏览器无响应。

因此,setState 调用是异步的,并且是批处理的,以获得更好的 UI 体验和性能。

可以在状态值更新后调用函数:

this.setState({foo: 'bar'}, () => {
// Do something here.
});

此外,如果您有很多状态要一次更新,将它们全部分组在同一个 setState中:

而不是:

this.setState({foo: "one"}, () => {
this.setState({bar: "two"});
});

照我说的做:

this.setState({
foo: "one",
bar: "two"
});

好文章在这里 https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setState.md

// assuming this.state.count === 0
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
// this.state.count === 1, not 3


Solution
this.setState((prevState, props) => ({
count: prevState.count + props.increment
}));

或通过回调 this.setState ({.....},callback)

Https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82 Https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b

我知道这个问题已经很老了,但是长期以来它已经给很多 reactjs 用户带来了很多困惑,包括我自己。 最近,反应小组的丹 · 阿布拉莫夫(Dan Abramov)刚刚写了一篇文章,对 setState的本质是异步的原因给出了很好的解释:

Https://github.com/facebook/react/issues/11527#issuecomment-360199710

setState意味着是异步的,在 Dan Abramov 的链接解释中有一些非常好的理由。这并不意味着它将 一直都是是异步的-它主要意味着你只是不能 取决于上它是 同步。ReactJS 考虑了您正在更改状态的场景中的许多变量,以决定实际更新 state和重新呈现组件的时间。
一个简单的例子可以证明这一点,如果你调用 setState作为对用户操作的反应,那么 state可能会立即更新(尽管,你不能指望它) ,所以用户不会感觉到任何延迟,但是如果你调用 setState作为对 Ajax 调用响应或者其他一些用户没有触发的事件的反应,那么状态可能会稍微延迟更新,因为用户不会真正感觉到这种延迟,它会通过等待批处理多个状态更新在一起并减少重新呈现 DOM 的次数来提高性能。

想象一下在某个组件中增加一个计数器:

  class SomeComponent extends Component{


state = {
updatedByDiv: '',
updatedByBtn: '',
counter: 0
}


divCountHandler = () => {
this.setState({
updatedByDiv: 'Div',
counter: this.state.counter + 1
});
console.log('divCountHandler executed');
}


btnCountHandler = () => {
this.setState({
updatedByBtn: 'Button',
counter: this.state.counter + 1
});
console.log('btnCountHandler executed');
}
...
...
render(){
return (
...
// a parent div
<div onClick={this.divCountHandler}>
// a child button
<button onClick={this.btnCountHandler}>Increment Count</button>
</div>
...
)
}
}

父组件和子组件都有一个计数处理程序。这样做是有目的的,因此我们可以在同一个 click 事件冒泡上下文中执行 setState ()两次,但是从两个不同的处理程序中执行。

正如我们所想象的,按钮上的单击事件现在将触发这两个处理程序,因为在冒泡阶段,事件从目标到最外层的容器冒泡。

因此 btnCountHandler ()首先执行,希望将计数增加到1,然后执行 divCountHandler () ,希望将计数增加到2。

然而,当您可以在 React Developer 工具中检查时,计数只增加到1。

这证明了那种反应

  • 对所有 setState 调用进行排队

  • 在执行上下文中的最后一个方法(本例中是 divCountHandler)后返回到此队列

  • 将发生在同一上下文中的多个 setState 调用中的所有对象突变(例如,一个事件阶段中的所有方法调用都是相同的上下文)合并为一个单一对象突变语法(合并是有意义的,因为这就是为什么我们可以首先在 setState ()中独立更新状态属性)

  • 并将其传递到一个 setState ()中,以防止由于多个 setState ()调用而重新呈现(这是批处理的非常原始的描述)。

由 response 运行的结果代码:

this.setState({
updatedByDiv: 'Div',
updatedByBtn: 'Button',
counter: this.state.counter + 1
})

为了停止这种行为,不再将对象作为参数传递给 setState 方法,而是传递回调。

    divCountHandler = () => {
this.setState((prevState, props) => {
return {
updatedByDiv: 'Div',
counter: prevState.counter + 1
};
});
console.log('divCountHandler executed');
}


btnCountHandler = () => {
this.setState((prevState, props) => {
return {
updatedByBtn: 'Button',
counter: prevState.counter + 1
};
});
console.log('btnCountHandler executed');
}

在最后一个方法完成执行之后,当 response 返回处理 setState 队列时,它只是为每个排队的 setState 调用回调,并传递上一个组件状态。

这种反应方式可以确保队列中的最后一个回调可以更新之前所有对应方都处理过的状态。

您可以使用下面的回绕来 < em > make sync call

this.setState((state =>{
return{
something
}
})

是的,setState ()是异步的。

链接: https://reactjs.org/docs/react-component.html#setstate

  • React 不能保证立即应用状态更改。
  • SetState ()并不总是立即更新组件。
  • 可以将 setState ()看作是一个请求,而不是一个用于更新组件的即时命令。

因为他们觉得
来自链接: < a href = “ https://github.com/facebook/response/issues/11527 # issecomment-360199710”rel = “ nofollow noReferrer”> https://github.com/facebook/react/issues/11527#issuecomment-360199710

... 我们同意 setState ()同步重新呈现在许多情况下是低效的

异步 setState ()让那些刚开始学习的人甚至是那些不幸经历过的人的生活变得非常困难:
- 意想不到的渲染问题: 延迟渲染或没有渲染(基于程序逻辑)
传递参数是件大事
还有其他问题。

下面的例子帮助:

// call doMyTask1 - here we set state
// then after state is updated...
//     call to doMyTask2 to proceed further in program


constructor(props) {
// ..


// This binding is necessary to make `this` work in the callback
this.doMyTask1 = this.doMyTask1.bind(this);
this.doMyTask2 = this.doMyTask2.bind(this);
}


function doMyTask1(myparam1) {
// ..


this.setState(
{
mystate1: 'myvalue1',
mystate2: 'myvalue2'
// ...
},
() => {
this.doMyTask2(myparam1);
}
);
}


function doMyTask2(myparam2) {
// ..
}

希望能帮上忙。

SetState 是异步的

有意识地“等待”,直到所有组件在其事件处理程序中调用 setState () ,然后才开始重新呈现。这样可以避免不必要的重新呈现,从而提高性能。

但是,您可能仍然想知道为什么 React 不立即更新 this. state 而不重新呈现。

原因是这样会打破道具和状态之间的一致性,导致很难调试的问题。

如果函数依赖于状态值的更改,则仍然可以执行:

选择1: 对 setState 使用回调函数

this.setState({
value: newValue
},()=>{
// It is an callback function.
// Here you can access the update value
console.log(this.state.value)
})

选项2: 使用 < a href = “ https://reactjs.org/docs/response-Component ent.html # Component entdiupdate”rel = “ nofollow noReferrer”> Component entDidUpdate 只要该特定类的状态发生变化,就会调用这个函数。

componentDidUpdate(prevProps, prevState){
//Here you can check if value of your desired variable is same or not.
if(this.state.value !== prevState.value){
// this part will execute if your desired variable updates
}
}