React重学笔记

生命周期

类组件

React v16 引入的 Fiber 协调引擎,比起老版本来说,为了提高协调效率,减少页面交互卡顿,React 的 Fiber引擎把协调从同步过程改进成了异步过程。

  • 渲染阶段是异步过程,主要负责更新虚拟 DOM( FiberNode )树,而不会操作真实DOM,这一过程可能会被 React
    暂停和恢复,甚至并发处理,因此要求渲染阶段的生命周期方法必须是没有任何副作用(Side-effect)的纯函数(Pure
    Function);
  • 提交阶段是同步过程,根据渲染阶段的比对结果修改真实 DOM,这一阶段的生命周期方法可以包含副作用。
    react中往往提交阶段很快,渲染阶段比较慢。

函数组件

1. 挂载阶段。

React 会执行组件函数,在函数执行过程中遇到的 useState 、 useMemo 等 Hooks 依次挂载到 FiberNode 上,useEffect 其实也会被挂载,但它包含的副作用(Side-effect,在 Fiber 引擎中称为 Effect)会保留到提交阶段。

组件函数的返回值通常会使用 JSX 语法,React 在渲染阶段根据返回值创建 FiberNode 树。在提交阶段,React 更新真实 DOM 之前会依次执行前面定义的 Effect。

2. 更新阶段。

当组件接收到新 props 或者 调用 useState 返回的 setter 或者 useReducer 返回的 dispatch 修改了状态,组件会进入更新阶段。

组件函数本身会被再次执行,Hooks 会依次与 FiberNode 上已经挂载的 Hooks 一一匹配,并根据需要更新。组件函数的返回值用来更新 FiberNode 树。

进入提交阶段,React 会更新真实 DOM。随后 React 会先执行上一轮 Effect 的清除函数,然后再次执行 Effect。这里的 Effect 包括 useEffect 与useLayoutEffect ,两者特性很相像。其中useLayoutEffect 的 Effect 是在更新真实 DOM 之后同步执行的,与类组件的 componentDidMount、componentDidUpdate 更相似一些;而 useEffect 的 Effect 是异步执行的,一般晚于 useLayoutEffect 。

3. 卸载阶段。

主要是执行 Effect 的清除函数。函数组件也有错误处理阶段,但没有对应的生命周期 Hooks,错误处理依赖于父组件或祖先组件提供的错误边界。

Hooks

官方文档

我的建议是,首先精通三个基础 Hooks,也就是 useState 、 useEffect 和 useContext。然后在此基础上:掌握

useRef 的一般用法;

  • 当需要优化性能,减少不必要的渲染时,学习掌握 useMemo 和 useCallback ;4
  • 当需要在大中型React 项目中处理复杂 state 时,学习掌握 useReducer ;
  • 当需要封装组件,对外提供命令式接口时,学习掌握 useRef加 useImperativeHandle;
  • 当页面上用户操作直接相关的紧急更新(UrgentUpdates,如输入文字、点击、拖拽等),受到异步渲染拖累而产生卡顿,需要优化时,学习掌握 useDeferredValue 和useTransition 。

在使用 Hooks 时务必注意。

第一,只能在 React 的函数组件中调用 Hooks。

这也包括了在自定义的 Hook 中调用其他 Hooks 这样间接的调用方式,目的是保证 Hooks 能"勾"到 React 的虚拟 DOM 中去,脱离 React 环境的 Hooks 是无法起作用的。

第二,只能在组件函数的最顶层调用 Hooks。

无论组件函数运行多少遍,都要保证每个 Hook 的执行顺序,这样 React 才能识别每个 Hook,保持它们的状态。当然,这就要求开发者不能在循环、条件分支中或者任何 return 语句之后调用 Hooks。

其实从 Fiber 协调引擎的底层实现来看,也不难理解上面两个限制。函数组件首次渲染时会创建对应的 FiberNode,这个 FiberNode 上会保存一个记录 Hooks 状态的单向链表,链表的长度与执行组件函数时调用的 Hooks 个数相同。

当函数组件再次渲染时,每个 Hook 都会被再次调用,而这些 Hooks 会按顺序,去这个单向链表中一一认领自己上一次的状态,并根据需要沿用或者更新自己在链表中的状态:

如果不在 React 的函数组件中调用 Hooks,React 就不会创建记录 Hooks 状态的单向链表;如果在循环、条件分支等不稳定的代码位置调用 Hooks,就有可能导致再次渲染时,执行 Hooks 的数量、种类和参数与上次的单向链表不一致,Hooks 内部的逻辑就乱掉了。


相关推荐
细节控菜鸡2 小时前
【2025最新】ArcGIS for JS 实现随着时间变化而变化的热力图
开发语言·javascript·arcgis
koo3642 小时前
李宏毅机器学习笔记30
人工智能·笔记·机器学习
摇滚侠2 小时前
Spring Boot 3零基础教程,WEB 开发 内嵌服务器底层源码分析 笔记48
spring boot·笔记
拉不动的猪3 小时前
h5后台切换检测利用visibilitychange的缺点分析
前端·javascript·面试
桃子不吃李子3 小时前
nextTick的使用
前端·javascript·vue.js
报错小能手3 小时前
项目——基于C/S架构的预约系统平台 (1)
开发语言·c++·笔记·学习·架构
赤月幼狼4 小时前
clickhouse学习笔记(一)基础概念与架构
笔记·学习·clickhouse
Devil枫5 小时前
HarmonyOS鸿蒙应用:仓颉语言与JavaScript核心差异深度解析
开发语言·javascript·ecmascript
惺忪97985 小时前
回调函数的概念
开发语言·前端·javascript
前端 贾公子5 小时前
Element Plus组件v-loading在el-dialog组件上使用无效
前端·javascript·vue.js