我刚刚发现,在任何组件中的react this.setState()
函数是异步的,或者在调用它的函数完成后被调用 .
现在我搜索并找到了这个博客(http://www.bennadel.com/blog/2893-setstate-state-mutation-operation-may-be-synchronous-in-reactjs.htm)
在这里,他发现 setState
是异步(在堆栈为空时调用)或同步(调用后立即调用),具体取决于触发状态变化的方式 .
现在这两件事很难消化
-
在博客中
setState
函数在函数updateState
中调用,但触发updateState
函数的函数不是被调用函数所知道的 . -
为什么他们会使
setState
async,因为JS是单线程语言,而这个setState不是WebAPI或服务器调用,所以必须只在JS的线程上完成 . 他们是这样做的,以便重新渲染不会停止所有事件监听器和东西,或者存在其他一些设计问题 .
5 回答
您可以在状态值更新后调用函数:
此外,如果您有许多州要立即更新,请将它们全部分组到同一个_1462790中:
1.)setState操作是异步的,并且为了性能提升而进行批处理 . 这在setState的文档中有解释 .
2.)为什么它们会使setState异步,因为JS是单线程语言,而这个setState不是WebAPI或服务器调用:
这是因为setState改变了状态并导致重新渲染 . 这可能是一项昂贵的操作,并使其同步可能会使浏览器无响应 .
因此,setState调用是异步的,也可以是批处理的,以获得更好的UI体验和性能 .
我知道这个问题已经过时了,但很长一段时间以来,包括我在内的很多反应用户都引起了很多困惑 . 最近Dan Abramov(来自反应小组)刚刚写了一个很好的解释,为什么
setState
的性质是异步的:https://github.com/facebook/react/issues/11527#issuecomment-360199710
setState
意味着是异步的,在Dan Abramov的链接解释中有一些非常好的理由 . 这并不意味着它将是异步的 - 它主要意味着你不能依赖于 synchronous . ReactJS考虑了您正在更改状态的场景中的许多变量,以确定何时应实际更新state
并重新呈现组件 .一个简单的例子来说明,如果你将
setState
作为对用户操作的反应,那么state
可能会立即更新(尽管如此,你可以感觉到任何延迟,但如果你对setState
的反应是一个ajax调用响应或其他一些事件确实没有感觉到这种延迟,它将通过等待批处理多个状态更新并重新渲染DOM更少次来提高性能 .好文章在这里https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setState.md
或传递回调
this.setState ({.....},callback)
https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82 https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b
想象一下在某个组件中递增计数器:
有一个计数处理程序附加到父组件和子组件 . 这是故意完成的,因此我们可以在相同的单击事件冒泡上下文中执行两次setState(),但是从2个不同的处理程序中执行 .
正如我们想象的那样,按钮上的单击事件现在将触发这两个处理程序,因为事件在冒泡阶段从目标气泡到最外面的容器 .
因此,btnCountHandler()首先执行,期望将计数增加到1然后执行divCountHandler(),期望将计数增加到2 .
但是,计数只会增加到1,因为您可以在React Developer工具中进行检查 .
这证明了反应
将所有setState调用排队
在执行上下文中的最后一个方法后回到此队列(在本例中为divCountHandler)
将同一上下文中多个setState调用内发生的所有对象突变(单个事件阶段中的所有方法调用都是相同的上下文)合并为一个单一的对象变异语法(合并有意义,因为这就是为什么我们可以更新状态属性独立于第一个中的setState()地点)
并将其传递给一个单独的setState()以防止由于多个setState()调用而重新呈现(这是一个非常原始的批处理描述) .
反应运行的结果代码:
要停止此行为,不要将对象作为参数传递给setState方法,而是传递回调 .
在最后一个方法完成执行并且react返回以处理setState队列之后,它只是为每个排队的setState调用回调,并传入前一个组件状态 .
这种方式反应可确保队列中的最后一个回调更新其所有先前的对应物已经完成的状态 .