🍪🧁🍧

Hook 原理

React Hook 原理

React Hook 允许我们在函数组件中使用 state 和其他 React 特性,其核心原理主要依赖以下几点:

1. 闭包 (Closures)

  • 每个 Hook (如 useState, useEffect) 在组件的每次渲染中被调用时,都会形成一个闭包。
  • useState 返回的 state 变量和 setState 函数,以及 useEffect 的回调函数,它们都能够“记住”它们被创建时的特定组件实例和特定的状态槽位。
  • setState 函数的身份通常是稳定的,但它内部知道要更新哪个组件的哪个状态。

2. 内部数据结构 (Hooks 链表/数组)

  • React 在内部为每个函数组件实例维护一个 Hooks 列表(通常被描述为链表或数组)
  • 当你调用 useState, useEffect 等 Hook 时,React 会按照它们被调用的顺序将 Hook 的信息(如 state 值、依赖项、effect 函数等)存储在这个列表中。
  • 关键点: 这就是为什么 Hooks 必须在组件的顶层调用,并且不能在循环、条件或嵌套函数中调用。React 依赖于每次渲染时 Hooks 的调用顺序完全一致,才能正确地从这个内部列表中获取和更新对应 Hook 的状态。
    • 第一次渲染时,useState() 调用将状态存储在列表的第一个位置,第二次 useState() 调用存储在第二个位置,以此类推。
    • 后续渲染时,React 再次按顺序调用这些 Hooks,并从对应位置取出之前存储的状态或信息。

3. Fiber 架构

  • React 的 Fiber 架构是实现 Hooks 的基础。Fiber 是 React 核心算法的重写,它使得渲染工作可以被中断、恢复以及分配优先级。
  • 每个组件实例在内存中都有一个对应的 Fiber 节点
  • Hook 的状态和相关信息就存储在这些 Fiber 节点的 memoizedState (或其他类似) 属性上,这个属性通常指向前面提到的 Hooks 链表的头部。
  • setState被调用时:
    1. React 会找到对应的 Fiber 节点。
    2. 标记该 Fiber 节点需要更新。
    3. 调度一次新的渲染。
    4. 在重新渲染该组件时,当再次执行到 useState,React 会从 Fiber 节点上读取当前 Hook 对应的最新状态值返回。

4. useState 的简要工作流程

  • 首次渲染:
    1. 调用 useState(initialState)
    2. React 创建一个新的 state 槽位(在组件的 Fiber 节点的 Hooks 链表中)。
    3. 存储 initialState
    4. 返回 [initialState, dispatchFunction] (即 setState)。
  • 后续渲染:
    1. 调用 useState() (此时不再需要 initialState 参数,React 会忽略它)。
    2. React 根据 Hook 的调用顺序,从 Fiber 节点的 Hooks 链表中找到对应的 state 槽位。
    3. 返回 [currentState, dispatchFunction]
  • 调用 setState(newState)setState(updaterFn)
    1. setState 函数被调用时,它不会立即修改 state。
    2. 它会创建一个更新对象,并将其调度到对应 Fiber 节点的更新队列中。
    3. React 调度器会在未来的某个时间点处理这个更新,触发组件的重新渲染。
    4. 如果使用的是函数式更新 setState(updaterFn),React 在执行更新时,会将当前最新的 state 作为参数传递给 updaterFn,并将返回值作为新的 state。

5. useEffect 的简要工作流程

  • 渲染完成后:
    1. 组件完成渲染并提交到 DOM 后,React 会执行 useEffect 的回调函数。
    2. 如果是首次执行,或者依赖项数组中的值与上一次渲染时相比发生了变化,回调函数会被执行。
    3. 如果回调函数返回了一个清理函数,React 会在下一次该 effect 即将重新执行之前,或者在组件卸载时,执行这个清理函数。
    4. React 会保存当前的依赖项数组,用于下一次比较。

总结来说,Hooks 通过闭包捕获信息,依赖于严格的调用顺序和 Fiber 节点上的内部存储来实现在函数组件中管理状态和副作用的能力。

posted @ 2025-05-14 23:29  不想吃fun  阅读(61)  评论(0)    收藏  举报