react的useMemo 如何优化?

好的,我们来深入讲讲 React 的 useMemo 以及它的优化思路。我们一步步拆解,确保你能真正理解什么时候用、怎么用,以及可能的坑。


1️⃣ useMemo 的本质

useMemo 是一个 性能优化 Hook ,它的作用是 缓存计算结果 ,避免在每次渲染时重复计算开销大的值。

语法:

scss 复制代码
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • 第一个参数:返回一个值的函数(这个值会被缓存)
  • 第二个参数:依赖数组,只有依赖发生变化时,函数才会重新执行

💡 核心:useMemo 不是用来缓存组件的渲染 ,而是用来缓存计算结果。


2️⃣ 典型使用场景

场景 1:开销大的计算

typescript 复制代码
function MyComponent({ number }) {
  const factorial = useMemo(() => {
    console.log('计算阶乘');
    let result = 1;
    for (let i = 2; i <= number; i++) {
      result *= i;
    }
    return result;
  }, [number]);

  return <div>{factorial}</div>;
}

✅ 优化点:

  • 如果没有 useMemo,每次父组件渲染,阶乘都会重新计算。
  • 用 useMemo 后,只有 number 改变时才计算。

场景 2:避免引用类型变化导致子组件重复渲染

javascript 复制代码
function Parent({ data }) {
  const filteredData = useMemo(() => data.filter(item => item.active), [data]);

  return <Child data={filteredData} />;
}
  • 如果不加 useMemo,每次渲染 Parent 时,filteredData 都是一个新数组,Child 会触发不必要的渲染。
  • 用 useMemo 缓存数组引用,减少 Child 渲染。

3️⃣ 使用 useMemo 的注意点

  1. 不要滥用

    • useMemo 本身也有开销(创建函数、比较依赖)。
    • 小计算、简单对象不要用,可能比不使用更慢。
    • 适合计算复杂、数据量大或依赖变化少的场景。
  2. 依赖数组必须准确

    • 缺失依赖会导致缓存结果不同步
    • 多余依赖会降低性能
  3. 不缓存副作用

    • useMemo 不能替代 useEffect
    • 它只是缓存值,不执行副作用(比如 API 请求)

4️⃣ 优化策略总结

  1. 缓存重计算值:

    • 复杂计算、大数组操作、大对象计算
    • 示例:阶乘、排序、过滤、聚合计算
  2. 缓存引用类型:

    • 避免每次渲染生成新的数组/对象,导致子组件不必要渲染
    • 常配合 React.memo 或 useCallback
  3. 分离组件:

    • 如果父组件渲染频繁,且子组件依赖开销大的计算,考虑用 useMemo 或拆成独立组件
  4. 依赖最小化:

    • 确保依赖数组只放必须的值,避免频繁失效

⚡ 小技巧

  • 配合 React.memo:
javascript 复制代码
const Child = React.memo(({ data }) => {
  console.log('Child 渲染');
  return <div>{data.length}</div>;
});

function Parent({ items }) {
  const activeItems = useMemo(() => items.filter(item => item.active), [items]);
  return <Child data={activeItems} />;
}
  • Child 只在 activeItems 改变时渲染,而不是每次 Parent 渲染。

  • 配合 useCallback 缓存函数:

    • 当函数作为 prop 传递时,避免引用变化
ini 复制代码
const handleClick = useCallback(() => console.log('点击'), []);
相关推荐
花开盛夏^.^1 天前
电脑打开多个浏览器Web窗口占用较大的运行内存的原因
前端·浏览器
馒头不想说话1 天前
实体店老板的24小时AI运营员工,写、剪、发全自动,省下一整个团队工资
前端
椒哥1 天前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
风骏时光牛马1 天前
生成一个AI稳定性治理及疑难问题分析标题,只需要一个标题,不需要其他的任何文本。
前端
莫西干式秃头1 天前
用 AI + threejs 写了个浏览器里的 3D 动作游戏《武来》:砍怪、放技能、开 SU7
前端·人工智能·three.js
kyriewen1 天前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员
孟健1 天前
用 WorkBuddy 做个人名片网页,挂上开源设计技能后效果完全不同了
前端·人工智能·ai编程
IT_陈寒1 天前
SpringBoot自动配置的坑,这次终于爬出来了
前端·人工智能·后端
LuHang1 天前
从天地图切换到高德地图:一次真实的底图迁移实战
前端·vue.js·cesium
用户360055579001 天前
Kestrel_VLLM - 27 · 寄存器常驻与融合发射:两次「少发一次」
前端