React Hook 解析(一):useCallback 与 useMemo

📘 本系列将系统解析 React 中的常用 Hooks,帮助你深入理解背后的原理与使用场景。本篇聚焦于两个性能优化利器:useCallback 和 useMemo。


✨ 为什么需要它们?

React 在组件每次重新渲染时,都会重新执行函数体:

  • 每个函数、对象、数组都重新创建新引用

  • 会导致子组件重复渲染

  • 会造成重复的复杂计算

我们可以用 useCallback 和 useMemo 来优化这些性能问题。


🔁 useCallback:缓存函数引用

✅ 基本用法

tsx 复制代码
const memoizedFn = useCallback(() => {
  // 逻辑...
}, [依赖项]);

每当依赖项不变时,返回的函数引用保持不变。

✅ 使用场景

  • 将事件函数传递给 React.memo 包裹的子组件,避免不必要的重新渲染

  • 减少事件绑定的频率(例如鼠标滚动、点击)

✅ 示例

tsx 复制代码
const handleClick = useCallback(() => {
  console.log('clicked');
}, []);

对比:

tsx 复制代码
const handleClick = () => {
  console.log('clicked');
};

不使用 useCallback,每次组件渲染都会新建一个 handleClick 函数,导致引用变化。


🧠 useMemo:缓存计算值

✅ 基本用法

tsx 复制代码
const memoizedValue = useMemo(() => {
  return expensiveComputation(input);
}, [input]);

只有当依赖 input 变化时才会重新执行 expensiveComputation。

✅ 使用场景

  • 缓存复杂计算结果

  • 避免创建新的对象、数组,防止触发子组件更新

  • 数据筛选、排序等逻辑

✅ 示例

tsx 复制代码
const filteredList = useMemo(() => {
  return list.filter(item => item.includes(keyword));
}, [list, keyword]);

🔄 与 React.memo 联动优化子组件渲染

tsx 复制代码
const Child = React.memo(({ onClick }: { onClick: () => void }) => {
  console.log('子组件渲染');
  return <button onClick={onClick}>Click</button>;
});
tsx 复制代码
const handleClick = useCallback(() => {
  console.log('clicked');
}, []);
<Child onClick={handleClick} />

如果不使用 useCallback,每次父组件重渲染都会导致 onClick 引用变化,从而让 Child 也重新渲染。


📌 useCallback vs useMemo 对比

特性 useCallback useMemo
返回值 函数 任何计算后的值
用途 缓存函数引用,避免重复定义 缓存计算结果,避免重复运算
常见使用场景 向子组件传递函数 缓存数组、对象、复杂计算
本质 useMemo(() => fn, deps) useMemo(() => value, deps)

🧷 注意事项

  • 只有在真正的性能瓶颈或子组件频繁渲染时再使用

  • 滥用可能引入复杂性

  • 依赖数组必须写全,防止缓存失效或 bug


✅ 小结

Hook 优化对象 典型场景
useCallback 函数 事件绑定、传递函数 props
useMemo 值 复杂计算、缓存数组/对象

📚 下一篇我们将解析:useEffect 的执行时机与副作用陷阱。

相关推荐
Acro8 分钟前
快给macOS 上的Grok Bot换一套皮肤
前端
flash俊杰11 分钟前
双引擎 OCR 编排:逐页判定、视觉优先、partial 语义与三层超时
前端
计算机魔术师11 分钟前
Reddit 每周被 Google 偷走 100 万次点击,CEO 摊牌了
前端
前端繁华如梦12 分钟前
用 React Three Fiber 做一栋能编辑的教学楼数字孪生
前端
前端繁华如梦17 分钟前
用 React Three Fiber 做一套智慧医院数字孪生:编辑器、大屏和 BIM 浏览器
前端
俊昭喜喜里2 小时前
理解全局跨域CORS配置
前端
锋行天下4 小时前
DeepSeek写Langgraph就是个大傻逼,一本正经胡说八道
前端·人工智能·后端
jktantan5 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript
计算机魔术师5 小时前
Anthropic官方插件被「寄生」,背后是同一类攻击又来了
前端
我命由我123455 小时前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理