浅谈useMemo与useCallback的区别与联系

useCallback 和 useMemo 是 React 中用于性能优化的两个核心 Hook,它们的核心区别在于缓存的内容和使用场景:


​​1. 核心区别​​

​​特性​​ ​​useCallback​​ ​​useMemo​​
​​缓存内容​​ 缓存函数(函数引用) 缓存计算结果(值)
​​语法​​ useCallback(fn, deps) useMemo(() => value, deps)
​​主要用途​​ 避免子组件因父组件重新渲染而无效更新 避免重复计算昂贵的值

​​2. 使用场景​​

​​useCallback​​

  • ​​传递回调函数给子组件​ ​:当子组件被 React.memo 包裹时,父组件传递的函数引用变化会导致子组件重新渲染。useCallback 可确保函数引用稳定。

    ini 复制代码
    const handleClick = useCallback(() => {
      // 逻辑
    }, [依赖项]);
    <ChildComponent onClick={handleClick} />
  • ​​依赖项作为其他 Hook 的参数​ ​:例如 useEffect 或另一个 useCallback,需确保依赖函数稳定。

    scss 复制代码
    useEffect(() => {
      fetchData(handleSuccess); // handleSuccess 需稳定
    }, [handleSuccess]);

​​useMemo​​

  • ​​复杂计算结果缓存​​:如大数据处理、格式转换等,避免每次渲染重复计算。

    ini 复制代码
    const filteredData = useMemo(() => {
      return data.filter(item => item.price > 100);
    }, [data]);
  • ​​优化引用类型变量​​:如对象、数组,避免因引用变化触发子组件渲染。

    ini 复制代码
    const config = useMemo(() => ({ theme: "dark" }), []);

​​3. 关键注意事项​​

  • ​​依赖数组​​:必须完整列出所有依赖项,否则可能导致闭包问题或无效缓存。

    scss 复制代码
    // 错误示例:依赖项缺失可能导致旧值引用
    const value = useMemo(() => data.value, []); // 应 [data]
  • ​​避免滥用​​:过度使用会增加内存开销,仅对性能敏感场景使用。

  • ​​与 React.memo 配合​ ​:useCallback 常与 React.memo 联用,优化组件渲染链。


​​4. 性能对比示例​​

​​useCallback 场景​​

ini 复制代码
// 父组件
const Parent = () => {
  const [count, setCount] = useState(0);
  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []); // 函数引用稳定

  return <Child onIncrement={increment} />;
};

// 子组件(React.memo)
const Child = React.memo(({ onIncrement }) => {
  // 仅在 onIncrement 变化时重新渲染
  return <button onClick={onIncrement}>+</button>;
});

​​useMemo 场景​​

javascript 复制代码
const ExpensiveComponent = ({ data }) => {
  const result = useMemo(() => {
    // 复杂计算(如排序、过滤)
    return data.sort((a, b) => a.value - b.value);
  }, [data]); // 数据变化时才重新计算

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

​​5. 总结​​

  • ​useCallback​:缓存函数引用,优化子组件渲染。
  • ​useMemo​:缓存计算结果,避免重复计算。
  • ​共同原则​:仅在必要时使用,依赖数组需完整,避免内存泄漏。
相关推荐
吴声子夜歌1 分钟前
Nginx应用与运维——Nginx Web服务应用实战(伪流媒体服务器的搭建)
运维·前端·nginx
ss27326 分钟前
AI全栈实战 | 2.4-01 Node 与前端工程化:前端为什么离不开 Node,它不只是构建工具的宿主
前端
aixingpan27 分钟前
aixingpan.cn API开发文档:api_docs_transit接口指南
前端·php
鬓戈30 分钟前
Volta:解决 nvm「不能同时存在多个 Node 版本」的痛点
前端
吴声子夜歌33 分钟前
Nginx应用与运维——Nginx Web服务应用实战(HTTP增强协议服务器的搭建)
运维·前端·nginx
扶风ff9 小时前
新品知识更新太快?用练题簿在线刷题,安排企业培训的小测与复盘
前端·学习·小程序
对空六课10 小时前
支持注意力分析的热力图工具有哪些?
前端·数据库·数据分析
Csvn11 小时前
Vue3 响应式与编译:依赖收集如何升级为节点级靶向更新
前端
星栈12 小时前
pnpm 12 升级实测
前端·javascript
Sirens.12 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法