React 的 useMemo 是怎么实现的?你自己能造一个吗?

30 次浏览次阅读
没有评论

React useMemo实现原理深度解析:从源码到手动实现

当Vue开发者初次接触React的useMemo时,往往会下意识地将其等同于computed属性。但当我们深入源码时会发现:useMemo本质上是一个带有依赖追踪的计算结果缓存系统,它更像是经过精密设计的备忘录而非响应式魔法。本文将带您穿透表象,解密其核心实现机制,并亲手打造一个简易版useMemo。

一、React useMemo的三大核心实现原理

1.1 Hooks的链表存储结构

React通过单向链表结构存储Hooks状态,每个useMemo对应链表中的一个节点。在组件首次渲染时创建包含三个关键属性的节点:

  • memoizedState:缓存的计算结果
  • dependencies:依赖项数组
  • queue:更新队列(用于调度重计算)

1.2 依赖对比算法

React采用浅比较(shallow compare)进行依赖项比对,其核心逻辑可简化为:

function areDependenciesEqual(prevDeps, nextDeps) {
  for(let i=0; i

1.3 缓存更新策略

当检测到依赖变化时,React会触发同步重计算而非异步更新。源码中的核心逻辑伪代码如下:

function updateMemo(create, deps) {
  const hook = updateWorkInProgressHook();
  const nextDeps = deps === undefined ? null : deps;
  
  if (hook.memoizedState !== null) {
    const prevState = hook.memoizedState;
    if (areDependenciesEqual(prevState.dependencies, nextDeps)) {
      return prevState.memoizedValue;
    }
  }
  
  const nextValue = create();
  hook.memoizedState = { 
    memoizedValue: nextValue,
    dependencies: nextDeps 
  };
  return nextValue;
}

二、手动实现一个简易版useMemo

2.1 存储系统设计

我们使用闭包变量模拟React的Hooks存储机制:

let memoCache = [];
let cursor = 0;

function resetCursor() {
  cursor = 0;
}

2.2 核心逻辑实现

function myUseMemo(create, deps) {
  // 初始化缓存节点
  if (!memoCache[cursor]) {
    memoCache[cursor] = {
      value: create(),
      deps: deps
    };
    cursor++;
    return memoCache[cursor到1].value;
  }

  // 依赖比对
  const shouldRecompute = deps.some((dep, i) => 
    !Object.is(dep, memoCache[cursor].deps[i])
  );

  if (shouldRecompute) {
    memoCache[cursor] = {
      value: create(),
      deps: deps
    };
  }

  cursor++;
  return memoCache[cursor-1].value;
}

2.3 与React实现的关键差异

  • 存储结构差异:使用数组替代链表,简化状态管理
  • 渲染周期处理:缺少React的渲染队列调度机制
  • 依赖处理:未实现React的自动依赖收集功能

三、使用useMemo的五个黄金准则

3.1 必须使用的场景

  • 复杂计算缓存:如矩阵运算、大数据量转换
  • // 计算斐波那契数列
      const fib = useMemo(() => {
        let a=0, b=1;
        for(let i=0; i<100000; i++) [a,b] = [b, a+b];
        return b;
      }, []);
  • 组件渲染优化:避免无效的子组件重渲染
  • const memoizedChild = useMemo(() => , [data]);

3.2 必须警惕的陷阱

  • 过早优化反噬:简单计算使用useMemo反而增加内存开销
  • 依赖数组陷阱:忘记更新依赖项会导致缓存失效
  • 副作用滥用:在useMemo中执行API调用等副作用操作

3.3 性能评估策略

console.time('expensiveCalc');
// 需要缓存的复杂计算
console.timeEnd('expensiveCalc'); // 超过1ms的计算才值得缓存

四、从原理到实践的正确认知

通过源码分析我们发现,useMemo本质上是一个依赖驱动的缓存系统,而非响应式状态管理工具。其实现亮点在于:

  1. 与React渲染流程深度集成的更新机制
  2. 基于Object.is的精确依赖比较算法
  3. 链表结构带来的多Hook协同能力

当我们在日常开发中遇到以下场景时,才是useMemo真正该登场的时候:

  • 计算耗时超过1ms的复杂逻辑
  • 需要保持引用稳定的对象/数组
  • 高频交互组件的渲染优化

记住:性能优化不是银弹,useMemo更不是装饰品。 只有理解其实现原理,才能让这个工具真正为你的应用加速。

正文完
 0

辉哥

一言一句话
-「
最新文章
淘宝一钻店铺出售值钱吗?价格怎么算?

淘宝一钻店铺出售值钱吗?价格怎么算?

淘宝一钻店铺出售值钱吗?价格怎么算? 在淘宝电商平台上,许多新手卖家和创业者都把“一钻”视为重要的里程碑。它代...
淘宝一钻店铺能转让吗?四钻网店大概多少钱?

淘宝一钻店铺能转让吗?四钻网店大概多少钱?

淘宝一钻店铺能转让吗?四钻网店大概多少钱? 随着淘宝电商平台的持续火热,越来越多的人选择开淘宝店创业。但经营店...
淘宝店铺可以转让吗?转让是否合法?

淘宝店铺可以转让吗?转让是否合法?

淘宝店铺可以转让吗?转让是否合法? 淘宝作为中国最大的电商平台,吸引了无数创业者和商家入驻。随着经营时间推移,...
淘宝真的有人卖店铺吗?知乎怎么看?

淘宝真的有人卖店铺吗?知乎怎么看?

淘宝真的有人卖店铺吗?知乎怎么看? 近年来,随着电商竞争越来越激烈,很多人在搜索引擎和知乎上频繁提问:“淘宝真...
淘宝有没有正规的店铺转让平台?去哪找?

淘宝有没有正规的店铺转让平台?去哪找?

淘宝有没有正规的店铺转让平台?去哪找? 随着电商行业的快速发展,越来越多的人希望通过淘宝开店创业。但从零开始建...
淘宝官方允许店铺转让吗?知乎上怎么说?

淘宝官方允许店铺转让吗?知乎上怎么说?

淘宝官方允许店铺转让吗?知乎上怎么说? 随着电商行业的快速发展,很多商家会因为业务调整、资金需求或个人原因考虑...
淘宝怎样把店铺转让给别人?还能看到以前订单吗?

淘宝怎样把店铺转让给别人?还能看到以前订单吗?

淘宝怎样把店铺转让给别人?还能看到以前订单吗? 随着电商行业的快速发展,很多淘宝卖家因为转行、资金需求或其他原...
淘宝已转让的店铺安全吗?后续会有风险吗?

淘宝已转让的店铺安全吗?后续会有风险吗?

淘宝已转让的店铺安全吗?后续会有风险吗? 随着电商创业热潮不减,许多人选择通过转让方式快速获取淘宝店铺,避免从...
淘宝网店怎么转让?常见流程有哪些?

淘宝网店怎么转让?常见流程有哪些?

淘宝网店怎么转让?常见流程有哪些? 在淘宝开网店是许多人创业的首选方式,但随着时间推移,不少店主因个人原因选择...
淘宝钻级店铺能转让吗?钻级店铺作用大吗?

淘宝钻级店铺能转让吗?钻级店铺作用大吗?

淘宝钻级店铺能转让吗?钻级店铺作用大吗?全面解析 近年来,淘宝电商平台竞争日益激烈,许多创业者希望快速切入市场...
想购买淘宝店铺应该怎么操作?流程清楚吗?

想购买淘宝店铺应该怎么操作?流程清楚吗?

想购买淘宝店铺应该怎么操作?流程清楚吗? 随着电商行业的快速发展,越来越多的人希望通过淘宝创业。但从零开始开店...