HOOKS 背后机制

js 复制代码
function UserProfile() {  
  // Hook 1: useState  
  const [name, setName] = useState('John');  
    
  // Hook 2: useEffect    
  useEffect(() => {  
    document.title = `用户: ${name}`;  
  }, [name]);  
    
  // Hook 3: useMemo  
  const displayName = useMemo(() => {  
    return name.toUpperCase();  
  }, [name]);  
    
  return <h1>{displayName}</h1>;  
}

React 内部会这样组织数据:

    1. Fiber 节点 :代表 UserProfile 组件
    1. Hook 链表 :useState → useEffect → useMemo → null
    1. 状态管理 :useState 的 Hook 对象包含当前值 'John' 和更新队列
    1. 副作用管理 :useEffect 的 Effect 对象存储在 Fiber 的副作用队列中
js 复制代码
// 基于 ReactFiberHooks.js 源代码的 Hook 类型定义  
export type Hook = {  
  memoizedState: any,                    // 💾 存储当前 hook 的状态值或缓存值  
  baseState: any,                        // 🎯 用于计算下一次 state 的基础 state  
  baseQueue: Update<any, any> | null,    // 🔄 存储跳过的低优先级 update  
  queue: any,                            // 📋 指向 UpdateQueue 对象,存储待处理的 update  
  next: Hook | null,                     // ➡️ 指向下一个 Hook 对象的指针  
};
js 复制代码
function UserProfile() {  
  const [name, setName] = useState('John');     // Hook 1  
  const [age, setAge] = useState(25);           // Hook 2  
    
  useEffect(() => {                             // Hook 3  
    console.log(`${name} is ${age} years old`);  
  }, [name, age]);  
    
  return <div>{name} ({age})</div>;  
}
js 复制代码
// Fiber.memoizedState 指向的 Hook 链表  
const hookChain = {  
  // Hook 1: useState(name)  
  memoizedState: 'John',           // 💾 当前 name 的值  
  baseState: 'John',               // 🎯 基础状态  
  queue: {                         // 📋 UpdateQueue 对象  
    pending: null,                 // 当前没有待处理的更新  
    dispatch: setName,             // setState 函数  
    lastRenderedState: 'John'  
  },  
  baseQueue: null,                 // 🔄 没有跳过的更新  
  next: {                          // ➡️ 指向下一个 Hook  
      
    // Hook 2: useState(age)  
    memoizedState: 25,             // 💾 当前 age 的值  
    baseState: 25,                 // 🎯 基础状态  
    queue: {  
      pending: null,  
      dispatch: setAge,  
      lastRenderedState: 25  
    },  
    baseQueue: null,  
    next: {  
        
      // Hook 3: useEffect  
      memoizedState: {             // 💾 Effect 对象  
        tag: 'Passive',            // useEffect 的标记  
        create: () => console.log(`${name} is ${age} years old`),  
        deps: ['John', 25],        // 依赖数组的当前值  
        destroy: undefined         // 清理函数(如果有的话)  
      },  
      queue: null,               // useEffect 没有更新队列  
      baseQueue: null,  
      next: null                 // 🔚 链表结束  
    }  
  }  
};

setName('Jane') 时,React 并不会立即更新状态,而是创建一个 "更新任务" 并放入队列中。这就是 UpdateQueue

// UpdateQueue 类型定义

export type UpdateQueue<S, A> = {

pending: Update<S, A> | null, // 📋 指向待处理更新的环形链表

lanes: Lanes, // 🚦 优先级标记

dispatch: (A => mixed) | null, // 🎯 setState 函数本身

lastRenderedReducer: ((S, A) => S) | null, // 🔄 上次使用的 reducer

lastRenderedState: S | null, // 💾 上次渲染的状态

};

// Update 对象类型定义

export type Update<S, A> = {

lane: Lane, // 🚦 本次更新的优先级

revertLane: Lane, // ↩️ 回滚优先级 (React 19 新增)

action: A, // 🎬 更新动作:值或函数

hasEagerState: boolean, // ⚡ 是否有预计算状态

eagerState: S | null, // 💡 预计算的状态值

next: Update<S, A>, // ➡️ 下一个更新(环形链表)

};

相关推荐
jktantan2 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
2601_962885723 小时前
quotes 字段全解:涨跌幅、振幅、换手率的口径与单位
java·前端·spring
excel3 小时前
encodeURI 和 encodeURIComponent 有什么区别?
前端
前端精髓3 小时前
调用openrouter的免费API模型
java·前端·javascript
赛博守夜人4 小时前
AI安全攻防与治理之十四:AI 安全测试不能脱离传统安全,Web、API、移动端与模型攻击面的组合拳
前端·人工智能·安全
开开心心_Every4 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
networknomad4 小时前
OpenReplay:自己搭的会话回放工具,给前端排错用的
前端·其他
缓慢更新5 小时前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
陈随易5 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
风骏时光牛马6 小时前
AI稳定性治理体系构建与疑难问题深度分析
前端