React状态更新是异步的,为了性能优化,状态更新都是批量更新的。
但是否可以确认 setState 调用后状态的更新顺序呢?
Dan Abramov 先给出了结论:
同一个组件中,setState 是否有确定的顺序?是的。
不同组件中,setState 是否有确定的顺序?是的。
状态始终是按照特定的顺序更新的。无论你是否看到介于两个状态之间的一个中间状态,无论你是否在批处理内。
目前(React 16 及更早版本),默认情况下,只有 React 事件处理程序中的更新才会被批处理。有一个不稳定(unstable)的 API 来强制在事件处理程序之外进行批处理,以便在需要时处理罕见的情况。
在未来的版本(可能是 React 17 或更高版本)中,React 将 默认批量更新所有更新
在 React 事件处理程序中,不论 setState() 调用了多少次,也不论 setState()被多少个组件调用,它们在事件结束时只会生成一次重新渲染
在这两个例子中,setState() 调用都发生在 React 事件处理程序中。因此,在事件结束时,他们总是被合并到一起(而且你看不到中间状态)
更新总是 按照它们发生的顺序进行浅合并(shallowly merge)
在 React 16 和更早版本中,React 事件处理程序之外还没有默认的批处理。因此,如果在例子中,我们把 handleClick 替换为 AJAX 处理程序,那么每个 setState() 都会立即处理。在这种情况下,你会看到一个中间状态:
promise.then(() => {
// 我们不在事件处理程序中,因此它们都会被刷新。
this.setState({a: true}); // 使用 {a: true, b: false } 重新渲染
this.setState({b: true}); // 使用 {a: true, b: true } 重新渲染
this.props.setParentState(); // 重新渲染父组件
});
我们认识到,_根据是否处于事件处理程序中,行为是不同的,这是不方便的。这将在未来的 React 版本中进行更改,默认情况下将批量更新所有更新(并提供选择性 API 以同步刷新更改)。直到我们切换默认行为(可能在 React 17 中),有一个 API 可以用来强制批量处理:
promise.then(() => {
// 强制批量处理
ReactDOM.unstable_batchedUpdates(() => {
this.setState({a: true}); // 不重新渲染
this.setState({b: true}); // 不重新渲染
this.props.setParentState(); // 不重新渲染
});
// 当我们退出 unstable_batchedUpdates函数后,重新渲染一次
});
在 React 内部,事件处理程序都被包装在 unstable_batchedUpdates 内,这就是默认情况下批处理的原因。请注意,将 setState 封装 unstable_batchedUpdates 两次是不起作用的。当我们退出最外层的unstable_batchedUpdates 调用时,更新被刷新。
原文: React 是否保持 state 更新的顺序?