react的setState使用详解
2019-08-01 本文已影响0人
Mr无愧于心
react修改状态是不能直接修改的,需要使用setState来进行状态的修改,但是setState的使用会存在一些问题。觉得有必要在此做一下总结。。。。
setState()不是立刻更新组件。其可能是批处理或推迟更新。这使得在调用setState()后立刻读取this.state的一个潜在陷阱。
就像这样:
incrementCount() {
this.setState({count: this.state.count + 1});
}
handleSomething() {
this.incrementCount();
this.incrementCount();
this.incrementCount();
}
调用了3次incrementCount方法, 期望this.state.count的值是3, 但最后却是1
本质上setState修改state的值是通过浅合并把新的值合并到state的对象上,如果多次修改,react会进行批次处理
类似于:
Object.assign(
previousState,
{count: state.count + 1},
{count: state.count + 1},
{count: state.count + 1},
)
之后的调用在同一周期中将会重写之前调用的值,因此数量仅会被加一。若之后的状态依赖于之前的状态,
解决这个问题的方式:
componentDidUpdate或一个setState回调(setState(updater, callback))
- 当中的每个方法都会保证在更新被应用之后触发
- updater函数接收到的prevState 和 props保证都是最新的
incrementCount() {
this.setState((state) => {
return {count: state.count + 1}
});
}
handleSomething() {
this.incrementCount();
this.incrementCount();
this.incrementCount();
}
setState什么时候会异步更新
setState的执行流程:
this.setState(newState)
==>
newState存入pending队列
==>
判断是否处于batch update
==>
如果是的话就保存组件月dirtyComponents中,
如果不是的话就遍历所有的dirtyComponents,调用updateComponent,更新pending state or props
在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中回头再说,
而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,
但是,有一个函数 batchedUpdates,这个函数会把 isBatchingUpdates 修改为 true,
而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。
- setState会导致re-rederning, 而re-rederning的代价是昂贵的, 所以他们会尽可能的把多次操作合并成一次提交。
- 因为当传入的是一个函数时,state读取的是pending队列中state的值
setState什么时候会异步更新, 什么时候会同步更新
React是根据isBatchingUpdates来合并更新的, 那么当调用setState的方法或者函数不是由React控制的话, setState自然就是同步更新了。
- 如componentDidMount等生命周期以及React的事件即为异步更新,这里不显示具体代码。
- 如自定义的浏览器事件,setTimeout,setInterval等脱离React控制的方法, 即为同步更新