glownight

返回

一句话终极结论#

useMemo 缓存「函数返回的值」,useCallback 缓存「函数本身」 两者都是为了防止重复创建引用,解决 React 重复渲染问题。


1. 核心对比表#

特性useMemouseCallback
缓存什么值 / 计算结果函数本身
返回什么计算好的数据缓存后的函数
解决问题避免重复昂贵计算避免子组件重复渲染
触发时机依赖变化时重新计算依赖变化时更换函数引用
等价写法useCallback(fn, deps)useMemo(() => fn, deps)

2. 代码直观对比#

① useCallback(缓存函数)#

给函数做缓存,保证函数引用不变 主要用于传递给子组件的函数,配合 React.memo 防止子组件重渲染。

// 缓存函数本身,依赖不变,函数地址就不变
const handleClick = useCallback(() => {
  console.log(count);
}, [count]); 

// 传递给子组件,引用不变 → 子组件不重渲染
<Child onClick={handleClick} /> 
jsx

② useMemo(缓存值)#

给计算结果做缓存,避免每次渲染都重算 主要用于耗时计算、对象、数组

// 缓存计算出来的值,依赖不变,值就不变
const expensiveValue = useMemo(() => {
  return count * 1000; // 模拟耗时计算
}, [count]);

// 缓存对象,保证引用不变
const userInfo = useMemo(() => ({ name: 'Tom', age: 20 }), []);
jsx

3. 最核心的本质#

React 靠「引用地址」判断是否变化

  • useCallback:让函数地址不变
  • useMemo:让数据/对象地址不变

地址不变 → React.memo 判定 props 不变 → 子组件不重渲染


4. 最佳使用场景#

✅ useCallback 场景#

需要把函数传给子组件时:

const fetchData = useCallback(() => {
  axios.get('/api');
}, []);
// 传递给被 memo 包裹的子组件
<Table fetchData={fetchData} />
jsx

✅ useMemo 场景#

  1. 耗时计算(过滤、排序大量数据)
  2. 传递给子组件的对象/数组
const options = useMemo(() => ({ pageSize: 10 }), []);
<Filter options={options} />
jsx

5. 满分答案#

  1. useCallback 缓存函数本身,用于优化子组件渲染
  2. useMemo 缓存计算结果,用于优化重复计算
  3. 两者都是依赖驱动,依赖不变,缓存就不变;
  4. 核心目的都是保持引用地址稳定,配合 React.memo 防止无效重渲染。

总结#

  • 想缓存函数 → 用 useCallback
  • 想缓存数据/计算值 → 用 useMemo
  • 都是性能优化工具,不要滥用
useMemo 和 useCallback 的区别是什么?
作者 glownight
发布于 2026年1月25日