useCallback

useCallback 是 React 中用于**"缓存函数"**的 Hook。它的核心作用可以用一句话概括:

让一个函数在组件重新渲染时,保持相同的引用地址(即不重新创建),除非它的依赖项发生了变化。


1. 为什么需要它?(核心痛点)

在 React 函数组件中,每次渲染时,函数体内的代码都会重新执行一次。这意味着,你在组件里定义的普通函数,每次渲染都会生成一个全新的函数对象(内存地址不同)。

jsx 复制代码
// ❌ 每次渲染,handleClick 都是一个全新的函数
function Parent() {
  const handleClick = () => { console.log('clicked'); };
  // ...
}

这会导致什么问题? 如果你把这个函数传给一个被 React.memo 包裹的子组件,子组件会因为 props 的引用变了(虽然逻辑一样),而被迫重新渲染,浪费性能。


2. 它怎么解决?

useCallback 把函数"包"起来,React 会记住这个函数,只要依赖项没变,下次渲染时直接复用上一次的函数引用。

jsx 复制代码
// ✅ 只要依赖项 [] 不变,handleClick 永远是同一个函数
function Parent() {
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []); // 空依赖 → 永远不变

  return <Child onClick={handleClick} />;
}

3. 语法与依赖

javascript 复制代码
const memoizedFn = useCallback(fn, deps)
  • fn:你想缓存的函数。
  • deps :依赖数组。当 deps 中的任意值发生变化时,useCallback 才会重新创建(更新)这个函数。

4. 和 useMemo 的区别(最容易混淆)

Hook 缓存内容 适用场景
useMemo 缓存计算结果(值、对象、数组) 昂贵的计算、稳定对象引用。
useCallback 缓存函数本身 把函数作为 prop 传给子组件,或作为 useEffect 的依赖项。

等价关系

javascript 复制代码
// useCallback 本质上就是 useMemo 的语法糖
useCallback(fn, deps) 等价于 useMemo(() => fn, deps)

5. 什么时候该用,什么时候不该用?(最佳实践)

  • 该用

    1. 当函数作为 props 传递给 React.memo 子组件时。
    2. 当函数作为 useEffect 的依赖项时(防止 Effect 无限循环)。
  • 不该用

    1. 函数只在当前组件内部使用,不往下传。
    2. 函数依赖了频繁变化的状态(此时用了也没意义,因为依赖变了它还是会重建)。

教训 :不要给所有函数都套上 useCallback,它会增加内存开销和代码复杂度。React 官方建议:只在有性能瓶颈时再优化


6. 举个实战例子

jsx 复制代码
function Search({ query }) {
  // ✅ 依赖 query,query变了才重新生成函数
  const fetchData = useCallback(() => {
    fetch('/api?q=' + query);
  }, [query]);

  useEffect(() => {
    fetchData(); // 依赖了 fetchData
  }, [fetchData]); // 如果不用 useCallback,这里会无限循环
}

在这个例子里,如果 fetchData 是普通函数,每次渲染都会变,useEffect 会无限执行。用 useCallback 锁住它,只在 query 变化时才触发,完美解决。

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