fat-cat

[toc]

hooks

hooks 优点

hooks 缺点

useCallback

useCallback 是一个允许你在多次渲染中缓存函数的 React Hook

useContext

useContext 是一个 React Hook,可以让你读取和订阅组件中的 context(上下文)

useDeferredValue

useDeferredValue 是一个 React Hook,可以让你延迟更新 UI 的某些部分

useEffect

useEffect 是一个 React Hook,它允许你 将组件与外部系统同步

useImperativeHandle

useImperativeHandle 是 React 中的一个 Hook,它能让你自定义由 ref 暴露出来的句柄

useImperativeHandle(ref, createHandle, dependencies?)

useMemo

useMemo 是一个 React Hook,它在每次重新渲染的时候能够缓存计算的结果

useReducer

useReducer 是一个 React Hook,它允许你向组件里面添加一个 reducer。

useRef

useRef 是一个 React Hook,它能帮助引用一个不需要渲染的值

useState

useState 是一个 React Hook,它允许你向组件添加一个 状态变量

useTransition

useTransition 是一个帮助你在不阻塞 UI 的情况下更新状态的 React Hook

React Hooks 原理深度解析(通俗易懂版)

React Hooks(如 useStateuseEffect)的核心原理,本质是React 利用函数组件的 Fiber 节点,通过链表结构存储 Hook 状态,严格按调用顺序匹配,实现状态的持久化与复用

我会用极简原理 + 核心机制 + 伪代码实现帮你彻底吃透,不绕弯子。


一、先搞懂核心前提

  1. 函数组件本身无状态:普通函数执行完就销毁,变量会被回收,无法保存状态;
  2. Hooks 把状态存在「组件外部」:状态不放在函数里,而是存在 React 管理的 Fiber 节点(组件在 React 内部的真实对象)上;
  3. 必须按顺序调用:Hooks 不能写在 if/for/函数嵌套 里,因为 React 靠调用顺序匹配状态。

二、Hooks 核心原理(3 大关键点)

1. 状态存储:用「链表」存所有 Hook

React 为每个函数组件创建一个 Fiber 节点,节点上有个专门属性:memoizedState。 这个属性是一个单向链表,每个节点对应一个 Hook:

// 伪代码:组件的 Fiber 节点结构
fiberNode = {
    memoizedState: {
        hook: {
            state: 0, // 第一个 Hook:useState(0) 的值
            next: {
                hook: {
                    state: false, // 第二个 Hook:useState(false) 的值
                    next: null, // 链表结尾
                },
            },
        },
    },
};

2. 状态匹配:严格依赖「调用顺序」

这是 Hooks 最重要的规则:不能在条件/循环中使用 Hooks。 因为 React 不看 Hook 名称,只看调用顺序

// 正确:顺序固定
function App() {
    const [num, setNum] = useState(0); // 顺序 1
    const [flag, setFlag] = useState(false); // 顺序 2
}

// 错误:顺序会变,React 匹配失败
function App() {
    if (flag) {
        const [num, setNum] = useState(0); // 有时执行,有时不执行
    }
    const [flag, setFlag] = useState(false);
}

3. 状态更新:替换链表节点 + 触发重渲染


三、极简伪代码:手写一个 useState(看懂就懂原理)

这是 React 官方 useState核心简化版,10 行代码看懂本质:

// 全局变量:记录当前组件、当前 Hook 位置
let currentComponentFiber;
let hookIndex;

function useState(initialState) {
    // 1. 拿到当前组件的 Hook 链表
    const hooks = currentComponentFiber.memoizedState;
    // 2. 按 调用顺序 取对应 Hook
    const currentHook = hooks[hookIndex];

    // 3. 首次渲染:初始化 Hook,存入状态
    if (!currentHook) {
        hooks[hookIndex] = {
            state: initialState, // 存初始值
        };
    }

    // 4. 定义更新函数:修改状态 + 触发重渲染
    const setState = (newState) => {
        hooks[hookIndex].state = newState; // 更新链表中的状态
        renderComponent(); // 触发组件重新渲染
    };

    // 5. 索引+1,匹配下一个 Hook,返回当前状态
    hookIndex++;
    return [hooks[hookIndex - 1].state, setState];
}

// 组件渲染时:重置索引,按顺序执行 Hooks
function renderComponent() {
    hookIndex = 0; // 关键!每次渲染都从 0 开始
    componentFunction(); // 执行函数组件,调用所有 Hooks
}

伪代码总结

  1. 首次渲染:创建 Hook 链表,存储所有状态;
  2. 更新渲染:重置索引,按顺序读取链表中的状态;
  3. 修改状态:直接改链表值,触发重渲染,重新读取。

四、其他 Hooks 原理(通用)

所有 Hooks 底层逻辑完全一致,只是功能不同:


五、一句话终极总结

React Hooks 就是:用 Fiber 节点的链表存储状态,靠固定调用顺序匹配 Hook,重渲染时按顺序读取状态,实现函数组件的状态持久化与副作用管理。


总结

  1. 状态位置:Hooks 状态存在组件 Fiber 节点,不在函数内部;
  2. 存储结构单向链表,一个 Hook 对应一个节点;
  3. 核心规则调用顺序绝对固定(不能用在条件/循环里);
  4. 更新机制:修改链表状态 → 触发重渲染 → 按顺序读取最新状态。