聊聊 setState 这个 API
React 是一个 MVVM 框架,倡导 数据驱动视图
的思想。页面数据的变化会引起 UI 重新渲染,并且页面中的数据流是单向的。在 React 里我们想触发 UI 渲染有两种方式: setState
以及 forceUpdate
,当然你还可以借助第三方库 redux 中的 API 等。今天就来认识下 setState
这个 API。
基本用法
setState 接收的参数,可以是一个对象,也可以是函数,函数里返回更新对象:
setState(updater[, callback])
如果是对象形式更新,类似这样:
this.setState({
count: this.state.count + 1
})
如果是函数形式更新,则函数返回值就是待更新的数据:
this.setState((prevsState) => {
return {count: prevsState.count + 1}
})
setState 是同步还是异步的?
通常情况下,setState 是异步的。从生命周期的角度看,每一次 setState 执行可能就触发了 UI 重新渲染,假如 setState 是同步的,那这样不停地渲染,可能页面就卡死了,因此把 setState 异步化,是为了避免频繁的重复渲染。实际上,每一次调用 setState,React 都会把更新操作放入一个队列,然后合并队列里相同的 state 做最终的状态更新,这也就是 批量更新
。也就是说,即使你在代码里,写个 100 次循环的 setState,React 也不会傻傻地一次次渲染,而是把操作都积攒起来,等到合适的时候再合并批量更新。
setState 内部是怎么工作的?
React 源码中 setState 的调用链路:
- setState
- enqueueSetState:将新的 state 放进一个状态队列,然后调用 enqueueUpdate 处理传入的待更新实例对象
- enqueueUpState:有一个 batchingStrategy 对象,判断该对象的 isBatchingUpdates 是否为 false,是则安排组件更新;否则将组件推入 dirtyComponents 里,暂缓更新。
- isBatchingUpdates ?
- Yes ,Enqueu dirtyComponents
- No,取出 dirtyComponents 所有组件,安排更新
当调用 batchUpdates 方法安排更新时,就会把 isBatchingUpdates 这个变量上锁,然后执行完更新后,再恢复回来。这个执行的过程涉及到 事务机制
,所谓事务机制,是 React 封装的一个 盒子,这个盒子把某个方法包装起来,然后提供了统一的 perform
, close
等 API 来执行。
当批量更新的事务执行时,首先上锁 isBatchingUpdates 为 true,然后循环调用 dirtyComponents 里所有组件,执行 updateComponent 来触发每个组件的生命周期执行,从而实现组件更新。最后解锁 isBatchingUpdates 置为 false。
总结
- 为了避免组件频繁渲染,setState 更新的过程是异步的,并且会合并批量更新
- 每次调用 setState 时,React 会先上锁,一旦有锁,所有 setState 操作都会进入队列,不会立即执行更新;React 会在合适的时候放开锁,进而执行渲染数据更新
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: React 性能优化
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论