React 中的 useCallback 入门指南:是真需要,还是假怪?

在学习 React 时,很多人初步接触 useCallback 都有一个同样的疑问:

“useCallback 到底是干啥的?不是简单地就是‘缓存一个函数’吗?我一直不明白它真正有什么用。”

这篇文章就来给你一个全方位、实操、有例实的 useCallback 入门指南,帮你真正理解它的作用。


1. useCallback 是什么?

它是 React 的一个 Hook,用来 缓存一个函数的引用,避免在组件重新渲染时重新创建该函数

基本用法:

const memoizedCallback = useCallback(() => {
  // ...
}, [deps]);

当 deps 不变化时,这个函数就不会重新创建。


2. 为什么需要 useCallback?

React 组件每次重新渲染,所有的函数都是重新创建的。如果这个函数传给了子组件,那子组件就会被认为改变了 props,不论其内部是否真正改变。

如果子组件是 React.memo() 缓存的,那么这个 props 函数的变化就会打破缓存,导致子组件重新渲染。

useCallback 的作用,就是保证函数引用 在 deps 不变化时不变,从而避免子组件无效重渲染。


3. 简单示例

const Child = React.memo(({ onClick }: { onClick: () => void }) => {
  console.log('Child 渲染了');
  return <button onClick={onClick}>子按钮</button>;
});

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

  const handleClick = useCallback(() => {
    console.log('Child 被点击');
  }, []);

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>增加计数</button>
      <Child onClick={handleClick} />
    </div>
  );
}

每次点击“增加计数”按钮,如果你用了 useCallbackChild 就不会重渲染。


4. TypeScript 下不加参数类型会有问题?

是的,当 TypeScript 打开 strict mode 时,如果 useCallback 的函数有参数却没有指定类型,就会报错。

const handleClick = useCallback((e) => {
  console.log(e.target);
}, []); // 报错:参数 'e' 类型不明

正确写法:

const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
  console.log(e.target);
}, []);

为什么会报错?因为 TypeScript 对不包含参数类型的函数无法精确推断类型,尤其是返回值是 void 时更是如此。


5. 什么时候需要用 useCallback?

适合场景:

  • 函数被传给子组件

  • 子组件用了 React.memo()

  • 子组件性能故事明显

不需要的场景:

  • 函数只在本地使用

  • 没有性能问题,例如组件很小或非常简单


6. 小结

useCallback 不是所有场景都需要用,但在需要性能优化时,它是非常有用的工具。它和 React.memo 结合,就像 React 性能优化的黄金伴侣,用好了可以效果显著;用错了反而可能使性能下降。

最好的做法是:需时之用,而不是一上来就翘翘地拿一堆 useCallback

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wen's

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值