浅谈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​:缓存计算结果,避免重复计算。
  • ​共同原则​:仅在必要时使用,依赖数组需完整,避免内存泄漏。
相关推荐
time_rg6 分钟前
深入理解react——2. Concurrent Mode
前端·react.js
0_17 分钟前
封装了一个vue版本 Pag组件
前端·javascript·vue.js
Stirner9 分钟前
A2UI : 以动态 UI 代替 LLM 文本输出的方案
前端·llm·agent
Code知行合壹12 分钟前
Vue.js进阶
前端·javascript·vue.js
我叫唧唧波17 分钟前
【微前端】qiankun基础
前端·前端框架
摸鱼的春哥17 分钟前
企业自建低代码平台正在扼杀AI编程的生长
前端·javascript·后端
-凌凌漆-19 分钟前
【JS】var与let的区别
开发语言·前端·javascript
火车叼位19 分钟前
使ast-grep-vscode 识别Vue组件
前端·visual studio code
YAY_tyy24 分钟前
综合实战:基于 Turfjs 的智慧园区空间管理系统
前端·3d·cesium·turfjs
生活在一步步变好i25 分钟前
模块化与包管理核心知识点详解
前端