深入理解React State 原理

 更新时间:2022年01月13日 08:35:48   作者:YuLong~W  
本文主要介绍了React State 原理,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

问题:setState 到底是同步还是异步的?

如果对 React 底层有一定了解,可以回答出 batchUpdate 批量更新概念,以及批量更新被打破的条件。

答案:有时是同步,有时是异步。

在 合成事件 和 生命周期函数 里是 异步 的在 原生事件 和 setTimeout、promise里是 同步

造成setState的异步并不是由内部的异步代码引起的,在本身的执行过程中时同步的,但是合成事件和生命周期函数的调用顺序在更新之前,导致在内部不能直接得到更新后的值,可以用第二个参数 callback 来获取。

具体解释:可参考setState的执行过程

类组件state

setState(obj,callback)

  • 第一个参数:当 obj 为一个对象,则为即将合并的 state ;如果 obj 是一个函数,那么当前组件的 state 和 props 将作为参数,返回值用于合并新的 state。
  • 第二个参数 callback :callback 为一个函数,函数执行上下文中可以获取当前 setState 更新后的最新 state 的值,可以作为依赖 state 变化的副作用函数,可以用来做一些基于 DOM 的操作。

一次事件中触发一次如上 setState ,在 React 底层执行过程:

render 阶段 render 函数执行 -> commit 阶段真实 DOM 替换 -> setState 回调函数执行 callback

在这里插入图片描述

首先,setState 会产生当前更新的优先级(老版本用 expirationTime ,新版本用 lane )。接下来 React 会从 fiber Root 根部 fiber 向下调和子节点,调和阶段将对比发生更新的地方,更新对比 expirationTime ,找到发生更新的组件,合并 state,然后触发 render 函数,得到新的 UI 视图层,完成 render 阶段。接下来到 commit 阶段,commit 阶段,替换真实 DOM ,完成此次更新流程。此时仍然在 commit 阶段,会执行 setState 中 callback 函数,到此为止完成了一次 setState 全过程。

setState原理揭秘

本质:React 底层调用 Updater 对象上的 enqueueSetState 方法

enqueueSetState():创建一个update,放入当前 fiber对象 的待更新队列中,最后开启调度更新,进入更新流程。

在这里插入图片描述

React 的 batchUpdate 批量更新

目的:多次 setstate 会让逻辑多停留在 js 运行层面,阻塞了浏览器绘制,因此需要批量更新

batchedEventUpdates ():

在这里插入图片描述

分析流程:

  • React 事件执行前通过 isBatchingEventUpdates=true 打开开关,开启事件批量更新
  • 当事件结束,通过 isBatchingEventUpdates=false 关闭开关
  • 在 scheduleUpdateOnFiber 中根据这个开关来确定是否进行批量更新

1)异步环境下,继续开启批量更新模式:

异步操作里面的批量更新规则会被打破,因此提供了手动批量更新方法: unstable_batchedUpdates

2)提升更新优先级:

提供了方法: flushSync,可以将回调函数中的更新任务,放在一个较高的优先级中优先执行

补充:flushSync 在同步条件下,会合并之前的 setState | useState

3)总结:React 同一级别更新优先级 关系是:

flushSync 中的 setState > 正常执行上下文中 setState > 异步 setTimeout ,Promise 中的 setState

函数组件state

const [ state , dispatch ] = useState(initData)

  • ① state 目的提供给 UI ,作为渲染视图的数据源
  • ② dispatch 改变 state 的函数,可以理解为推动函数组件渲染的渲染函数
  • ③ initData 初始值

initData的初始值

  • 第一种情况是非函数,将作为 state 初始化的值
  • 第二种情况是函数,函数的返回值作为 useState 初始化的值

dispatch的参数

  • 第一种非函数情况,此时将作为新的值,赋予给 state,作为下一次渲染使用
  • 第二种是函数的情况,如果 dispatch 的参数为一个函数,这里可以称它为reducer,reducer 参数,是上一次返回最新的 state,返回值作为新的 state

监听 state 变化

useEffect :常可以把 state 作为 依赖项 传入 useEffect 第二个参数 deps ,但是注意 useEffect 初始化会默认执行一次

dispatch更新特点

与类组件一样,但是当调用改变 state 的函数dispatch,在本次函数执行上下文中,是获取不到最新的 state 值的

在这里插入图片描述


原因:函数组件更新就是函数的执行,在一次执行过程中,函数内部所有变量重新声明,所以改变的 state 只有在下一次函数执行时才更新。

useState 原理在之后 Hooks 讲解

问:类组件中的 setState 和函数组件中的 useState 有什么异同?

答:相同点:

  • 原理:setState 和 useState 更新视图,底层都调用了 scheduleUpdateOnFiber 方法,而且事件驱动情况下都有批量更新规则
  • 语法:第一个参数都可以传入函数

不同点:

  • 在不是 pureComponent 组件模式下, setState 不会浅比较两次 state 的值。只要调用 setState 就会执行更新。但是 useState 中 dispatchAction 会默认比较两次state是否相同来更新组件
  • setState 有专门监听 state 变化的回调函数 callback,可以获取最新 state。但是 useState 只能通过 useEffect 来执行 state 变化引起的副作用
  • setState 在底层处理逻辑时将旧 state 进行合并处理,而 useState 是重新赋值

到此这篇关于深入理解React State 原理的文章就介绍到这了,更多相关React State 原理 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 封装一个最简单ErrorBoundary组件处理react异常

    封装一个最简单ErrorBoundary组件处理react异常

    这篇文章主要介绍了一个处理react异常的ErrorBoundary组件,简单实用,代码详细,对这个组件感兴趣的朋友可以参考下
    2021-04-04
  • React中hook函数与useState及useEffect的使用

    React中hook函数与useState及useEffect的使用

    这篇文章主要介绍了React中hook函数与useState及useEffect的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • react native环境安装流程

    react native环境安装流程

    React Native 是目前流行的跨平台移动应用开发框架之一。本文介绍react native环境安装流程及遇到问题解决方法,感兴趣的朋友一起看看吧
    2021-05-05
  • 详解如何使用React Hooks请求数据并渲染

    详解如何使用React Hooks请求数据并渲染

    这篇文章主要介绍了如何使用React Hooks请求数据并渲染,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • React Hooks钩子中API的使用示例分析

    React Hooks钩子中API的使用示例分析

    在react类组件(class)写法中,有setState和生命周期对状态进行管理,但是在函数组件中不存在这些,故引入hooks(版本:>=16.8),使开发者在非class的情况下使用更多react特性
    2022-08-08
  • 详解如何用webpack4从零开始构建react开发环境

    详解如何用webpack4从零开始构建react开发环境

    这篇文章主要介绍了详解如何用webpack4从零开始构建react开发环境,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • React手写tab切换问题

    React手写tab切换问题

    今天介绍下React手写tab切换问题,代码部分包括父文件,子文件及子文件tab样式,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2021-11-11
  • react同构实践之实现自己的同构模板

    react同构实践之实现自己的同构模板

    这篇文章主要介绍了react同构实践之实现自己的同构模板,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • react+antd树选择下拉框中增加搜索框

    react+antd树选择下拉框中增加搜索框

    这篇文章主要介绍了react+antd树选择下拉框中增加搜索框方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • React Native悬浮按钮组件的示例代码

    React Native悬浮按钮组件的示例代码

    本篇文章主要介绍了React Native悬浮按钮组件的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2018-04-04

最新评论