useMemo 和 useCallback 的区别,我终于搞懂了

useMemo 和 useCallback 的区别,我终于搞懂了

前言

刚开始学习 React Hooks 时,我一直分不清 useMemo 和 useCallback。

因为它们长得非常像:

javascript 复制代码
const value = useMemo(() => {
  return result
}, [])

const fn = useCallback(() => {
  console.log("hello")
}, [])

甚至依赖数组的写法都一样。

学习了一段时间后,我发现:

useMemo 缓存的是"值",useCallback 缓存的是"函数"。

这是两者最核心的区别。


什么是 useMemo

useMemo 用于缓存计算结果。

语法:

scss 复制代码
const memoizedValue = useMemo(() => {
  return compute()
}, [deps])

例如:

javascript 复制代码
const total = useMemo(() => {
  console.log("执行计算")

  return price * count
}, [price, count])

当:

复制代码
price
count

没有变化时,

React 不会再次执行计算逻辑。

直接返回上一次缓存结果。


useMemo 解决什么问题

假设有一个商品列表:

ini 复制代码
const products = [...]

需要筛选:

ini 复制代码
const filteredProducts = products.filter(...)

如果组件频繁重新渲染:

scss 复制代码
setInputValue(...)

即使商品数据没变化,

filter 也会不断执行。

这时可以使用:

scss 复制代码
const filteredProducts = useMemo(() => {
  return products.filter(...)
}, [products])

避免重复计算。


什么是 useCallback

useCallback 用于缓存函数。

语法:

ini 复制代码
const memoizedFn = useCallback(() => {
  ...
}, [deps])

例如:

javascript 复制代码
const handleClick = useCallback(() => {
  console.log("点击")
}, [])

依赖不变时,

返回同一个函数引用。


useCallback 解决什么问题

React 每次渲染时:

javascript 复制代码
function App() {
  const handleClick = () => {}

  return <Child onClick={handleClick} />
}

实际上:

复制代码
handleClick

会被重新创建。

即:

yaml 复制代码
旧函数 !== 新函数

如果:

复制代码
Child

使用了:

复制代码
React.memo

那么仍然会重新渲染。

因为:

复制代码
props变化了

此时可以使用:

scss 复制代码
const handleClick = useCallback(() => {}, [])

让函数引用保持不变。


最简单的记忆方法

记住一句话:

复制代码
useMemo 缓存结果

useCallback 缓存函数

例如:

ini 复制代码
const total = useMemo(() => {
  return price * count
}, [price, count])

缓存的是:

复制代码
100
200
300

这些计算结果。


javascript 复制代码
const handleClick = useCallback(() => {
  console.log("hello")
}, [])

缓存的是:

bash 复制代码
function

本身。


Vue 开发者如何理解

如果你是 Vue 开发者。

可以这样记:

useMemo

类似:

复制代码
computed
javascript 复制代码
const total = computed(() => {
  return price.value * count.value
})

缓存计算结果。


useCallback

Vue 中没有完全对应概念。

因为 Vue 模板编译阶段已经做了很多优化。

React 更关注:

复制代码
函数引用是否变化

所以才有 useCallback。


useMemo 和 useCallback 对比

对比项 useMemo useCallback
缓存内容 值 函数
返回值 计算结果 函数
常见场景 大数据计算 传递事件函数
对应Vue computed 无明显对应

一个常见误区

很多初学者会这样写:

javascript 复制代码
const handleClick = useCallback(() => {
  console.log("hello")
}, [])

整个项目到处都是:

复制代码
useCallback

实际上:

这样并不一定提升性能。

因为:

useCallback 本身也有维护成本。

React 需要:

  • 保存缓存
  • 对比依赖

如果函数很简单:

arduino 复制代码
() => console.log("hello")

完全没必要使用。


什么时候应该使用

推荐使用场景:

useMemo

  • 大量数据计算
  • 排序
  • 过滤
  • 聚合统计

例如:

yaml 复制代码
1000+
10000+

条数据处理。


useCallback

  • 传递给子组件
  • React.memo 配合使用
  • 自定义 Hook 返回函数

例如:

ini 复制代码
<Child onClick={handleClick} />

面试回答模板

如果面试官问:

"useMemo 和 useCallback 的区别是什么?"

我会这样回答:

useMemo 用于缓存计算结果,返回的是一个值;useCallback 用于缓存函数,返回的是一个函数引用。两者都依赖依赖数组控制是否重新生成。通常 useMemo 用于优化复杂计算,useCallback 用于避免函数重复创建,尤其是在 React.memo 场景下减少子组件不必要渲染。


总结

一句话记忆:

useMemo:

缓存计算结果。

useCallback:

缓存函数引用。

不要为了优化而优化,只有在组件存在实际性能问题时,再合理使用它们。

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95274 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大4 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师4 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学4 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端