为什么setState是异步的

96
strong9527
0.6 2018.02.06 08:56* 字数 685

总结博文

github上面dan解释了为什么react setState为什么是异步的。

前提:

首先我们都应该同意如果setState()方法同步re-render在很多情况下是很差的选择。将setState的改变的效果进入队列,并在某个特定的时间节点合并,一起刷新state是一个很好的机制。

举个例子:如果我们给父节点和子节点两个组件,都绑定了点击事件,当他们要触发setState的时候,我们并不希望事件的冒泡,导致子节点被re-render两次。我们更希望将父子节点标记为dirty(脏)组件,在
事件结束之前,一起re-render父子节点。

下面是dan给出的两个理由:

1.保证内部(数据)统一

首先,我们假定setState是同步的那么:


console.log(this.state.value) // 0
this.setState({ value: this.state.value + 1 });
console.log(this.state.value) // 1
this.setState({ value: this.state.value + 1 });
console.log(this.state.value) // 2


这种只用到了state的情况下,同步setState是可以的。

但是如果有props参与到了传值,那么同步setState模式就会有问题,比如我们把
state提升到了父组件,利用props将值传导子组件:

console.log(this.props.value) // 0
this.props.onIncrement();
console.log(this.props.value) // 0
this.props.onIncrement();
console.log(this.props.value) // 0


导致这样的结果主要原因是:当setState同步改变父节点state的时候,父节点传递给子节点的props是不能同步刷新的,原因是上面提到的背景:setState时同步re-render是很差的机制,这一点已经成为了共识,无法同步re-render就无法同步刷新this.props这就导致了子节点props数据,和父节点state值不一致,这就破坏了保证内部数据统一。

2.setState异步更新状态使得并发更新组件成为可能

首先我们在这里讨论是否同步刷新state有一个前提那就是我们默认更新节点是遵循特定的顺序的。但是按默认顺序更新组件在以后的react中可能就变了。

在以后的react的更新机制中,我们可能加入setState优先级这一概念。

举个例子:比如你现在正在打字,那么TextBox组件需要实时的刷新。但是当你在输入的时候,来了一个信息,这个时候,可能让信息延后刷新可能更符合交互。

异步rendering不仅仅是性能上的优化,而且这可能是react组件模型在发生的根本性的改变。

当然这个理由,可能是react发展的一个方向,目前还没有实现。

setState总结:

setState总结
react 全家桶