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 内部的逻辑就乱掉了。


相关推荐
听忆.5 分钟前
手机屏幕上进行OCR识别方案
笔记
ZL不懂前端30 分钟前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x34 分钟前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
Selina K43 分钟前
shell脚本知识点记录
笔记·shell
1 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
我血条子呢1 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落1 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
霍格沃兹测试开发学社测试人社区2 小时前
软件测试学习笔记丨Flask操作数据库-数据库和表的管理
软件测试·笔记·测试开发·学习·flask
理想不理想v2 小时前
vue经典前端面试题
前端·javascript·vue.js