面试官:useMemo 是性能神器?我:别乱用,优化不成反背锅!

123 阅读3分钟

👨‍🏫 本系列由前端面试真题博主 Kincy 发起,每日更新一题,通勤路上轻松掌握高频知识点。
📢 如果你想第一时间获取更新,或与群友交流面试经验、内推信息,欢迎加入微信群(文末扫码)!

🧠 系列前言:

面试题千千万,我来帮你挑重点。每天一道,通勤路上、蹲坑时、摸鱼中,技术成长不设限!本系列主打幽默 + 深度 + 面霸必备语录,你只管看,面试场上稳拿 offer!

💬 面试官发问:

“React 中 useMemo 和 useCallback 是干嘛的?它们怎么优化性能的?什么时候该用,什么时候不该用?”

哼哼,这题是 Hooks 界的“灵魂拷问”!

答不清楚,你就是乱抹防晒霜——看起来在优化,其实是白抹。

🎯 快答区(面霸速记版)

  • useMemo(fn, deps) 返回 fn() 的计算结果,用于缓存
  • useCallback(fn, deps) 返回 fn 本身,用于缓存函数引用
  • 它俩的存在就是为了避免无意义的重新计算或重新创建函数

如果组件频繁渲染、子组件依赖 props 变化,这俩钩子就能让你“一键优化、性能暴涨”

🧪 一、为什么需要 useMemo 和 useCallback?

你写了一个简单函数组件:

function App() {
  const result = heavyCalculation(data)

  return <Child value={result} />
}

每次父组件更新,heavyCalculation() 就会重新执行,哪怕 data 根本没变!

于是你写:

const result = useMemo(() => heavyCalculation(data), [data])

✅ 如果 data 没变,就复用上一次的计算结果

🔁 二、useCallback 和 useMemo 有啥区别?

来看这两个定义:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])
const memoizedFn = useCallback(() => handleClick(id), [id])

简单粗暴地记:

  • useMemo 是缓存
  • useCallback 是缓存函数

其实这俩内部原理一样,本质上:

useCallback(fn, deps) === useMemo(() => fn, deps)

👶 三、你可能踩过这些坑...

❌ 误区 1:以为它会“自动提升性能”

const memoizedFn = useCallback(() => {
  console.log('点击了')
}, [])

你这样写没有任何必要。这个函数根本不依赖任何变化,用不用 useCallback 都没啥区别。

🚨 它不会自动加速,只在“你真的在频繁重新创建函数/值”时才值得用!

❌ 误区 2:一股脑加 everywhere

const value = useMemo(() => 1 + 1, [])

你是认真的吗兄弟?1 + 1 也要缓存?

React:你用计算器能做的事,别拿我当缓存仓库啊!

📦 四、和 React.memo 配合食用,效果更佳!

你有一个子组件:

const Child = React.memo(({ onClick }) => {
  console.log('子组件渲染!')
  return <button onClick={onClick}>点我</button>
})

每次父组件重新渲染,如果 onClick 是新函数,React.memo 就失效,还是会更新。

这时你需要:

const handleClick = useCallback(() => {
  doSomething()
}, [])

<Child onClick={handleClick} />

完美:子组件不更新,函数不变,性能稳定!

🧩 五、源码小窥探(简化版)

React 内部其实是这么判断是否需要重新执行:

if (areHookInputsEqual(prevDeps, nextDeps)) {
  return previousResult
} else {
  const result = computeFn()
  saveResult(result)
  return result
}

areHookInputsEqual 就是你熟悉的 浅比较(Object.is),所以记得依赖项不能随手创建新对象:

const obj = { a: 1 } // 每次 render 都是新对象

要想避免重新执行,要么用 useMemo 创建,要么别放对象进去。

🎓 六、装 X 语录(限时使用)

“useMemo 和 useCallback 的本质是缓存机制,目的是减少不必要的重新计算和子组件重渲染。”

“它们配合 React.memo 使用,才能发挥真正的性能优化作用。”

“盲目使用只会徒增复杂度,记住一句话:有性能问题再上 memo。”

✅ 总结一句话

useMemo / useCallback 是缓存值和函数的神器,但不是优化万金油,切记“按需使用”!

🔮 明日预告

明天我们聊聊 useRef:一个让人误以为只能“引用 DOM”的钩子,其实它是 Hook 版的“仓库管理员”!🏪

📌 点赞 + 收藏 + 关注系列,Hook 的坑你一个都不会踩!

📚 本系列每天一题,持续更新中!
👉 扫码加入【前端面试题交流群】,一起成长、交流、内推、分享机会!

微信二维码.png 备注“掘金”优先通过