React状态更新是异步的,为了性能优化,状态更新都是批量更新的。
可是否能够确认 setState 调用后状态的更新顺序呢?
考虑如下按钮点击的例子:
是否有可能 a 是 false,b 是 true?java
import React, { PureComponent } from 'react'; class Subclass extends PureComponent { state = { a: true, b: true } handleClick = () => { this.setState({ a: false, b: false }); } render() { return <button onClick={this.handleClick}>Click</button> } }
是否有可能 a 是 false,b 是 true?react
class Parent extends PureComponent { state = { a: false } render() { return <Sub setParentState={this.setState.bind(this)}/> } } class Sub extends PureComponent { state = { b: false } handleClick = () => { this.props.setParentState({ a: true }); this.setState({ b: true }); } render() { return <button onClick={this.handleClick}>Click</button> } }
Dan Abramov 先给出告终论:git
同一个组件中,setState 是否有肯定的顺序?是的。 不一样组件中,setState 是否有肯定的顺序?是的。
状态始终是按照特定的顺序更新的。不管你是否看到介于两个状态之间的一个中间状态,不管你是否在批处理内。
目前(React 16 及更早版本),默认状况下,只有 React 事件处理程序中的更新才会被批处理。有一个不稳定(unstable)的 API 来强制在事件处理程序以外进行批处理,以便在须要时处理罕见的状况。
在将来的版本(多是 React 17 或更高版本)中,React 将 默认批量更新全部更新
在 React 事件处理程序中,不论 setState() 调用了多少次,也不论 setState()被多少个组件调用,它们在事件结束时只会生成一次从新渲染
在这两个例子中,setState() 调用都发生在 React 事件处理程序中。所以,在事件结束时,他们老是被合并到一块儿(并且你看不到中间状态)
更新老是 按照它们发生的顺序进行浅合并(shallowly merge)
在 React 16 和更早版本中,React 事件处理程序以外尚未默认的批处理。所以,若是在例子中,咱们把 handleClick 替换为 AJAX 处理程序,那么每一个 setState() 都会当即处理。在这种状况下,你会看到一个中间状态:github
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
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 更新的顺序?性能优化