# setState 详解

# 异步更新

setState用来更新 state 进而触发 re-render 更新视图.可是它是异步更新, 意思是我调用setState后, this.state并没有随即发生变化:

我在handleClick里连续三次使用了setState结果它只更新了一次.要理解这种现象, 要先改变对setState的理解, 要把它看作 请求(request) 而非立即更新组件的命令. 当调用setState后会发起更新请求, React 对请求进行批处理(batch), 换句话说, 更新请求会先被搁置, 也许过一会儿又有几个更新请求过来.就像下面的小朋友们一样排队等候.然后 React 再一起处理.

wash

对于传入对象参数的调用方式, React 会将后面的对象会覆盖之前的对象, 这等价于:

var newObj = Object.assign(
  {},
  { name: "jobs", age: 12 },
  { name: "jobs", age: 12 }
);

console.log(newObj); // {name: 'jobs', age: 12}
1
2
3
4
5
6
7

因此, 连续三次调用this.setState({ n: this.state.n + 1 });只会被合并成一次this.setState({ n: this.state.n + 1 });, 所以在控制台里看到更新的n1.

# 什么时候更新 state

既然不能立即更新state,那么什么时候会呢? 我通过打 log 的方法在各个生命周期里发现staterender 函数里更新了. 但是当shouldComponentUpdate返回的是false时,state仍然会更新.

# 为何要异步更新

有以下两点原因:

  1. 目前 React 会将 setState 的效果放在队列中, 积攒着一次引发更新过程, 为的就是把 Virtual DOM 和 DOM 树操作降到最小, 用于提高性能.

  2. shouldComponentUpdate需要用this.state来保留更新前的状态.一旦setState改为同步更新, shouldComponentUpdate也就废掉了.

# 传入函数的setState

不多逼逼, 先上代码:

这下, state就一下子累加到3了, React 通过函数的方式, 用参数state进行累加, 保证了下次调用setState时的参数state已经更新(注意: this.state并没有更新), 最后将参数state更新到this.state上. 这太牛逼了.