React中useMemo与useCallback区别以及各自解决什么性能问题、依赖陷阱详解

 更新时间:2026年05月18日 10:18:24   作者:光影少年  
useCallback和useMemo是一样的东西,只是入参有所不同,这篇文章主要介绍了React中useMemo与useCallback区别以及各自解决什么性能问题、依赖陷阱的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

这是 React 面试里非常高频的问题。你有前端经验,直接从本质、解决的问题、区别、依赖陷阱、实际场景理解会更快。

一、先理解 React 为什么会有 useMemo / useCallback

函数组件每次重新渲染:

function App() {
  const a = 1;

  const fn = () => {
    console.log(a);
  };

  return <Child fn={fn} />;
}

每次 App render:

fn1 !== fn2

函数是新的引用。

对象也是:

{ name: '张三' } !== { name: '张三' }

新的引用会导致:

  • 子组件重新渲染
  • 大量计算重复执行
  • memo 失效

所以 React 提供缓存:

缓存值 → useMemo
缓存函数 → useCallback

二、useMemo

作用:

缓存计算结果(value)

语法:

const value = useMemo(
  () => expensiveFn(a, b),
  [a, b]
);

等价于:

依赖没变:
返回上次结果

依赖变:
重新执行计算

场景1:避免复杂计算重复执行

错误:

function App({ list }) {

  const total = list.reduce(
      (sum,item)=>sum+item.price,
      0
  );

  return <div>{total}</div>
}

每次 render:

都会重新算:

O(n)

优化:

const total = useMemo(() => {
    return list.reduce(
        (sum,item)=>sum+item.price,
        0
    );
},[list]);

只有 list 变:

才重新计算。

解决问题:

避免高开销计算

比如:

  • 排序
sort()
  • filter
filter()
  • reduce
reduce()
  • 大数据处理
  • 图表计算
  • PDF 导出计算

你做性能平台经常会遇到。

场景2:保持对象引用稳定

错误:

<Child options={{
   page:1,
   size:10
}}/>

每次:

{} !== {}

Child 重渲染。

优化:

const options = useMemo(() => ({
    page:1,
    size:10
}),[]);

<Child options={options}/>

三、useCallback

作用:

缓存函数

语法:

const fn = useCallback(() => {

},[deps]);

等价于:

const fn = useMemo(
   ()=>()=>{},
   [deps]
)

所以:

useCallback ≈ useMemo(返回函数)

错误:

function App(){

 const click=()=>{
      console.log("点击")
 }

 return <Child onClick={click}/>
}

每次 render:

click1 != click2

子组件重新渲染。

优化:

const click = useCallback(()=>{

},[]);

函数引用稳定。

解决问题:

避免子组件无意义渲染

常搭配:

React.memo()

例如:

const Child = React.memo(
    ({onClick})=>{

}
);

只有:

props变化

才重渲染。

否则:

父更新
↓
子不更新

四、两者区别(面试回答)

可直接背:

对比useMemouseCallback
缓存什么函数
返回计算结果函数
解决问题重复计算函数引用变化
常见用途大数据计算、对象缓存事件函数缓存
搭配React.memoReact.memo

一句话:

useMemo 缓存结果
useCallback 缓存方法

五、依赖陷阱(重点)

这是面试官最爱问的。

陷阱1:依赖遗漏(闭包陷阱)

错误:

const [count,setCount]=useState(0);

const add = useCallback(()=>{
    console.log(count);
},[]);

依赖:

[]

永远缓存第一次:

输出:

0
0
0

不是最新值。

因为闭包:

记住旧 count。

应写:

const add = useCallback(()=>{
   console.log(count)
},[count]);

陷阱2:依赖过多导致失效

错误:

const options = {
   page,
   size
}

const fn = useCallback(()=>{

},[options]);

每次:

options 新对象

导致:

缓存失效
重新创建函数

应:

[page,size]

陷阱3:滥用 useMemo/useCallback

很多人:

const a = useMemo(()=>1,[]);

没意义。

因为:

缓存也有成本:

比较依赖
存缓存
维护引用

小计算:

直接写:

const a=1;

更快。

陷阱4:以为用了 useCallback 就优化了

错误:

const fn = useCallback(()=>{},[]);

但:

<Child fn={fn}/>

Child 不是:

React.memo()

仍会渲染。

优化失败。

通常配合:

useCallback + React.memo

六、什么时候不要用

不要:

const fn = useCallback(()=>{},[])
const obj = useMemo(()=>({}),[])

到处包。

会让代码:

  • 更复杂
  • 更难维护
  • 不一定更快

真正需要时:

用 useMemo

有昂贵计算:

排序
filter
大列表
图表
PDF
Excel

用 useCallback

函数传给:

React.memo 子组件
useEffect 依赖
事件回调

面试总结版(30 秒回答):

useMemo 用来缓存计算结果,避免重复执行昂贵计算;useCallback 用来缓存函数引用,避免子组件因函数变化重复渲染。useMemo 返回值,useCallback 返回函数。常见陷阱是依赖遗漏导致闭包问题、依赖对象导致缓存失效,以及滥用缓存造成额外开销。实际优化通常配合 React.memo 使用。

到此这篇关于React中useMemo与useCallback区别以及各自解决什么性能问题、依赖陷阱详解的文章就介绍到这了,更多相关React useMemo与useCallback区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入浅析React中diff算法

    深入浅析React中diff算法

    React 最为核心的就是 Virtual DOM 和 Diff 算法,diff算法的基础是Virtual DOM,接下来通过本文给大家介绍React中diff算法的相关知识,对React中diff算法感兴趣的朋友跟随小编一起学习下吧
    2021-05-05
  • React Native悬浮按钮组件的示例代码

    React Native悬浮按钮组件的示例代码

    本篇文章主要介绍了React Native悬浮按钮组件的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2018-04-04
  • React18中startTransition与useTransition的使用

    React18中startTransition与useTransition的使用

    本文主要介绍了React18中startTransition与useTransition的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • React 源码调试方式

    React 源码调试方式

    这篇文章主要为大家介绍了React源码调试方式实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • React如何使用create-react-app创建react项目

    React如何使用create-react-app创建react项目

    这篇文章主要介绍了React如何使用create-react-app创建react项目问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • React hook 'useState' is called conditionally报错解决

    React hook 'useState' is calle

    这篇文章主要为大家介绍了React hook 'useState' is called conditionally报错解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 实例讲解React 组件生命周期

    实例讲解React 组件生命周期

    这篇文章主要介绍了React 组件生命周期的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • react源码层探究setState作用

    react源码层探究setState作用

    写react的时候,踩了几次坑发现setstate之后state不会立刻更新,于是判定setstate就是异步的方法,但是直到有一天,我想立刻拿到更新的state去传参另一个方法的时候,才问自己,为什么setstate是异步的?准确地说,在React内部机制能检测到的地方,setState就是异步的
    2022-10-10
  • 使用webpack搭建react开发环境的方法

    使用webpack搭建react开发环境的方法

    本篇文章主要介绍了使用webpack搭建react开发环境的方法,在这篇文章中我们开始利用我们之前所学搭建一个简易的React开发环境,用以巩固我们之前学习的Webpack知识。一起跟随小编过来看看吧
    2018-05-05
  • 使用React实现一个简单的待办事项列表的示例代码

    使用React实现一个简单的待办事项列表的示例代码

    这篇文章我们将详细讲解如何建立一个这样简单的列表,文章通过代码示例介绍的非常详细,对我们的学习或工作有一定的帮助,需要的朋友可以参考下
    2023-08-08

最新评论