react16中的hooks的底层实现原理

 更新时间:2025年09月29日 10:06:49   作者:光影少年  
本文主要介绍了react16中的hooks的底层实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

好的 👍,你问的是 React 16 中所有 Hooks 的底层实现和原理

这里我会分几个层次来解释:

  1. React 16 的背景
  2. Hooks 的设计理念
  3. 核心 Hooks 的底层实现思路(useStateuseEffectuseContext, …)
  4. React 内部的 Hook 数据结构
  5. 执行流程(函数组件渲染时 Hook 的调用顺序)

1. 背景:React 16 与 Hooks

  • React 16.8 是第一个支持 Hooks 的版本。
  • 目标:让函数组件具备状态(state)和副作用(effect)的能力,替代部分 class 组件逻辑(比如 componentDidMount / componentDidUpdate / componentWillUnmount)。
  • 核心思想通过“调用顺序”来匹配 Hook 与组件的 fiber 节点,避免显式 id

2. Hooks 的设计理念

React Hooks 有几个原则:

  1. 只能在函数组件顶层调用,不能在条件语句或循环里动态调用。
    • 这是因为 Hooks 依赖调用顺序来定位。
  2. 只能在 React 函数组件或自定义 Hook 中调用
  3. 每个组件 fiber 节点维护一个单链表,链表节点就是 Hook 对象。

👉 这就是为什么 eslint-plugin-react-hooks 会强制规则:不要在 if/for 中调用 Hook

3. 常见 Hooks 的底层原理

(1)useState

  • 本质是 useReducer 的语法糖。
  • 内部维护一个 Hook 节点对象(链表的一部分):
type Hook = {
  memoizedState: any,     // 当前的 state
  baseState: any,         // 初始 state
  queue: UpdateQueue,     // 更新队列(链表结构)
  next: Hook | null       // 指向下一个 Hook
}
  • 当你调用 useState(initial) 时:
    • 创建一个更新对象(action)。
    • 挂到 queue 上。
    • 触发 scheduleUpdateOnFiber,进入调度。
    1. React 在当前 fiber 上创建一个 Hook 节点,memoizedState = initial
    2. 返回 [state, dispatch]
    3. dispatch 本质是一个函数:
  • 渲染时,React 会执行 processUpdateQueue,消费 queue,更新 memoizedState

(2)useEffect

  • 保存副作用函数和依赖数组。
  • Hook 节点结构:
type Effect = {
  tag: HookFlags,          // effect 类型(Passive, Layout 等)
  create: () => (() => void) | void,  // 副作用函数
  destroy?: () => void,    // 清理函数
  deps: any[] | null,      // 依赖
  next: Effect | null
}
  • 调用 useEffect(fn, deps) 时:
    • 如果 deps 变了,就调用上一次的 destroy(清理),再执行新的 create
    • 如果没变,则跳过。
    1. React 在 Hook 节点里记录 create 和 deps
    2. 在 commit 阶段(DOM 更新后),React 比较新旧依赖:

(3)useLayoutEffect

  • 和 useEffect 类似,但执行时机不同:
    • useLayoutEffect 在 DOM 更新后、浏览器绘制前 执行(同步)。
    • useEffect 在 浏览器绘制后 执行(异步,延迟)。
  • 用于测量 DOM、同步操作。

(4)useContext

  • 获取 Context 的值。
  • 机制:
    • 组件调用 useContext(MyContext) 时,会在 fiber 上记录对 MyContext 的依赖。
    • 当 Context Provider 的值变化时,React 会找到所有依赖它的消费 fiber,触发更新。

(5)useReducer

  • 类似 Redux 的 reducer:
    • useState 底层其实就是 useReducer 的特例:

      useState(initial) === useReducer((s, a) => typeof a === 'function' ? a(s) : a, initial)
      
  • 保存 reducer 和 state,通过 dispatch 触发更新。

(6)useRef

  • 维护一个 { current: any } 对象,整个生命周期内保持引用不变。
  • 实现:只在 Hook 节点里存一个 memoizedState = { current: initialValue },之后不会更新。

(7)useMemo/useCallback

  • 本质是“带缓存的值 / 函数”。
  • Hook 节点保存 value 和 deps
  • 渲染时对比依赖数组:
    • 如果没变,直接返回旧值。
    • 如果变了,重新计算并缓存。

4. React 内部 Hook 数据结构

在 fiber 节点上,每个函数组件对应一个 Hook 链表

type Fiber = {
  memoizedState: Hook | null; // hook 链表头
  updateQueue: any;
  // ...
}
  • renderWithHooks 函数:
    • 进入函数组件渲染时,初始化 currentlyRenderingFiber
    • 每调用一个 Hook,就在链表上走一步,复用或新建节点。
    • 保证 “调用顺序一致 = Hook 顺序一致”。

5. Hook 执行流程总结

  1. 初次渲染
    • 执行函数组件,依次调用 useState / useEffect …
    • 为每个 Hook 创建一个 Hook 节点,挂到 fiber.memoizedState 链表上。
  2. 更新渲染
    • 执行组件时,React 会遍历 fiber.memoizedState 链表。
    • 每次调用 Hook,就拿到对应节点,复用之前的状态。
    • 如果调用顺序错了(比如把 Hook 放到 if 里),链表错位,React 会报错。
  3. 提交阶段(commit phase)
    • 对于 useEffect / useLayoutEffect,会根据依赖比较来执行副作用。
    • 对于 useState / useReducer,会处理更新队列,得到新 state。

✅ 总结:

  • React Hooks 的底层实现是 fiber 节点上的 Hook 链表 + 调用顺序保证
  • 每个 Hook 维护一个小的状态对象,存储 memoizedStatequeuedeps 等。
  • useState 基于更新队列;useEffect 延迟到 commit 阶段执行;useRef 只是一个稳定对象;useMemo / useCallback 做依赖比较。

到此这篇关于react16中的hooks的底层实现原理的文章就介绍到这了,更多相关react16 hooks底层原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React条件渲染实例讲解使用

    React条件渲染实例讲解使用

    在React中,你可以创建不同的组件来封装各种你需要的行为。然后还可以根据应用的状态变化只渲染其中的一部分。React 中的条件渲染和JavaScript中的一致,使用JavaScript操作符if或条件运算符来创建表示当前状态的元素,然后让React根据它们来更新UI
    2022-11-11
  • React不能将useMemo设置为默认方法原因详解

    React不能将useMemo设置为默认方法原因详解

    这篇文章主要为大家介绍了React不能将useMemo设置为默认方法原因详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2022-07-07
  • react-redux action传参及多个state处理的实现

    react-redux action传参及多个state处理的实现

    本文主要介绍了react-redux action传参及多个state处理的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 详解React项目中碰到的IE问题

    详解React项目中碰到的IE问题

    这篇文章主要介绍了React项目中碰到的IE问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 实例讲解React 组件

    实例讲解React 组件

    这篇文章主要介绍了React 组件的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • 关于React项目中的PDF展示解决方案

    关于React项目中的PDF展示解决方案

    这篇文章主要介绍了关于React项目中的PDF展示解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • React Hooks获取数据实现方法介绍

    React Hooks获取数据实现方法介绍

    这篇文章主要介绍了react hooks获取数据,文中给大家介绍了useState dispatch函数如何与其使用的Function Component进行绑定,实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • React中CSS模块冲突的问题及解决

    React中CSS模块冲突的问题及解决

    本文将探讨 React 中 CSS 模块冲突的常见原因,并提供解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • react类标签的生命周期详解

    react类标签的生命周期详解

    在React类组件中,生命周期方法是非常重要的概念,它们允许我们在组件的不同阶段执行代码,这包括在组件挂载、更新以及卸载时执行的生命周期方法,本文通过介绍React类组件中的生命周期方法,旨在帮助开发者深入理解组件的生命周期管理
    2024-11-11
  • React Native自定义标题栏组件的实现方法

    React Native自定义标题栏组件的实现方法

    今天讲一下如何实现自定义标题栏组件,我们都知道RN有一个优点就是可以组件化,在需要使用该组件的地方直接引用并传递一些参数就可以了,这种方式确实提高了开发效率。对React Native自定义标题栏组件的实现方法感兴趣的朋友参考下
    2017-01-01

最新评论