浅谈useMemo与useCallback的区别与联系

useCallbackuseMemo 是 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 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
炫饭第一名4 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫4 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊4 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter4 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折4 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_4 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
Angelial5 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu5 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu5 小时前
Angular6学习笔记13:HTTP(3)
前端