React Hook & 周边技术原理

ReactHook

ReactHook 思维导图

Fiber Node 结构

这里只关系与 hooks 实现有关的内容

属性名 类型 说明
tag Number 组件类型。如这个组件是类组件、函数式组件,或其它什么类型的组件。
type Function String Symbol Number Object FiberNode的类型。对于Component类的组件,type就是它的Class名。对于函数式组件来说,type就是这个FiberNode对应的函数本身。
memoizedState Object 当前 state。 具体的说,这是组件的第一个Hook (组件hook作为一个环形单向链表存在)
updateQueue Object 更新队列。记录了React组件更新的副作用,在EffectHook中会谈到。

Hook (memoizedState)

这指的是Fiber.memoizedState 的链表项内容

属性名 类型 说明
memoizedState any hook的当前值 (不同的hook有不同的结构)
queue UpdateQueue<any, any> null 当前hook的更新队列
next Hook null 这个hook后面的一个hook

为什么 hook 是一个环形链表 ?为了性能考虑,如果用数组,插入和删除复杂度高

如果使用单向链表,插入需要遍历到最后,使用环形链表比较好

Dispatcher

React 根据渲染阶段的不同,使用不同的 dispatcher ,执行其中的函数(hook)

  • 挂载 HooksDispatcherOnMount (通过当前hook是否为空判断) --> 绑定更新函数到 fiber 上
  • 更新 HooksDispatcherOnUpdate --> 读取旧状态,合并更新队列,计算新值触发更新
  • 一个在渲染过程中触发的再次更新: HooksDispatcherOnRerender
  • 用于错误处理的:(在非法位置调用hook)ContextOnlyDispatcher --> 抛出异常(在执行完渲染后再切换回这里)
javaScript 复制代码
const HooksDispatcherOnMount: Dispatcher = {
  useEffect: mountEffect,
  useMemo: mountMemo,
  useState: mountState,
  ...
};

const HooksDispatcherOnUpdate: Dispatcher = {
  useEffect: updateEffect,
  useMemo: updateMemo,
  useState: updateState,
  ...
};

流程

state

  1. 挂载

    1. 首次调用的时候,将 hook 数据挂载到 WIP Fiber 上 (memorizedState) 形成一个 单向链表

    2. 使用 HooksDispatcherOnMount ,此时 Hook 调用 mountXXX 方法,初始化状态,绑定更新函数

      1. 生成的 dispatch 除了通过 bind 绑定了当前上下文,还提前传入的 FiberNode 等参数
    3. 最终返回 [ state ,dispatch ]

  2. 更新 ( 调用 setState )

    1. 从当前 Current 树中获取旧 Fiber 的 hook 数据
    2. 通过 HooksDispatcherOnUpdate ,创建 action 推入 推入对应 hook 的 queue 上
    3. 触发调度 ,开始构建 WIP 树 : 通过 updateWorkInProgressHook 从 Current 中取出旧状态,计算并更新到新的 WIP 的 Hook 链表中
    4. 调度器根据优先级判断是否需要中断/重组任务队列

effect

  1. 挂载

    1. 首次调用的时候,HooksDispatcherOnMount 调用 mountEffect 方法,创建 Effect 对象

      1. 挂载到 WIP 树到 updateQueue 环形链表中 (创建的时候需要执行一次)
  2. 更新

    1. 在 beforeMutation 阶段,通过与当前 current 树上的 effect 的依赖的对比,判断是否需要执行 updateQueue 中的函数(打标)
    2. 最后在执行完更新,调度执行 updateQueue 。 保存 destory 函数(在Effect对象内)
  3. 卸载

    1. 卸载的时候需要执行 Effect 的所有 destory 函数

Effect List

Effect List 副作用链在 compeletWork 环节收集,收集的内容是 fiber 节点上的 Effect 副作用 和 DOM 操作函数。

EffectList 会在commit 阶段执行三次遍历

  1. Before Mutation 异步调度 effect (messageChannel 宏任务)
  2. Mutation 同步执行 DOM
  3. Layout 同步执行 layoutEffect (此时DOM还没有渲染,只是挂载,所以能够防止闪屏)

Redux 单项数据流

React-Router

笔者才疏学浅,各位读者多多担待,不吝赐教。

相关推荐
HaanLen5 小时前
React19源码系列之Hooks(useRef)
javascript·react.js
前端大白话5 小时前
React 中shouldComponentUpdate生命周期方法的作用,如何利用它优化组件性能?
react.js
凉生阿新5 小时前
【React】基于 React+Tailwind 的 EmojiPicker 选择器组件
前端·react.js·前端框架
公子小六5 小时前
ASP.NET Core WebApi+React UI开发入门详解
react.js·ui·c#·asp.net·.netcore
学渣y6 小时前
React-响应事件
前端·javascript·react.js
晚风3086 小时前
React
react.js
IT、木易6 小时前
React 中shouldComponentUpdate生命周期方法的作用,如何利用它优化组件性能?
前端·javascript·react.js
Jia87087 小时前
实现你的第一个React项目
react.js
wfsm15 小时前
React多层级对象改变值--immer
前端·javascript·react.js
一个天蝎座 白勺 程序猿15 小时前
JavaScript性能优化实战手册:从V8引擎到React的毫秒级性能革命
javascript·react.js·性能优化