React 是否保持 state 更新的顺序

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 更新的顺序?性能优化

相关文章
相关标签/搜索