Skip to content
 

useCallback

更新: 9/4/2025字数: 0 字 时长: 0 分钟

介绍

useCallback 用于优化性能,返回一个记忆化的回调函数,可以减少不必要的重新渲染,也就是说它是用于缓存组件内的函数,避免函数的重复创建。

为什么需要 useCallbackReact 中,函数组件的重新渲染会导致组件内的函数被重新创建,这可能会导致性能问题。useCallback通过缓存函数,可以减少不必要的重新渲染,提高性能。

用法

tsx
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

使用

场景:父组件传递一个回调函数给子组件,如果父组件重新渲染,子组件会因为接收到新的回调函数而重新渲染(即使 props 没变)。

tsx
import React, { useEffect, useState, memo } from "react";

interface ChildProps {
  onClick: () => void;
}

const Child = memo(({ onClick }: ChildProps) => {
  console.log("Child 渲染了!"); // 每次父组件渲染,这里都会打印
  useEffect(() => {
    console.log("Child useEffect 运行了!"); // 父组件每次渲染,这里都会打印
  });
  return <button onClick={onClick}>子组件的点击</button>;
});

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

  const handleClick = () => {
    console.log("点击了");
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>增加 Count</button>
      <div></div>
      <Child onClick={handleClick} />
    </div>
  );
}

export default Parent;

在这个案例中:

1、count 变化时,Parent 会重新渲染吗?
✅ 会,因为 count 是 Parent 的状态,状态变化会触发组件重新渲染。

2、 Child 也会重新渲染吗?
❌ 默认不会,因为 Child 用 React.memo 包裹了,它会浅比较 props。
但在这个例子中,Child 仍然会重新渲染,因为 handleClick 每次都是新的函数。

解决方案如下:

使用 useCallback 包裹handleClick函数,这样子组件就不会每次重新创建了

tsx
 // ✅ 使用 useCallback 缓存函数,依赖数组为空表示不依赖任何变量 
 const handleClick = useCallback(() => {
   console.log("点击了");
 }, []);

我见青山多妩媚,料青山见我应如是。