聊聊 setState 这个 API

发布于 2023-11-02 17:42:51 字数 1845 浏览 44 评论 0

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 封装的一个 盒子,这个盒子把某个方法包装起来,然后提供了统一的 performclose 等 API 来执行。

当批量更新的事务执行时,首先上锁 isBatchingUpdates 为 true,然后循环调用 dirtyComponents 里所有组件,执行 updateComponent 来触发每个组件的生命周期执行,从而实现组件更新。最后解锁 isBatchingUpdates 置为 false。

总结

  • 为了避免组件频繁渲染,setState 更新的过程是异步的,并且会合并批量更新
  • 每次调用 setState 时,React 会先上锁,一旦有锁,所有 setState 操作都会进入队列,不会立即执行更新;React 会在合适的时候放开锁,进而执行渲染数据更新

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

拔了角的鹿

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文