何时使用 useCallback - ReactJS?

2025-06-08

何时使用 useCallback - ReactJS?

这篇文章没有“是/否”的答案,但试图从初学者的角度解释为什么这个钩子是官方名册的一部分。

让我们从两个部分开始讲这个故事:

  1. 父母
  2. 孩子

父组件有一个按钮,可以增加同一组件中的计数状态,而子组件与此无关。

点击“重新渲染”时,请注意控制台日志。子组件和父组件都会重新渲染并显示以下日志:

re-render parent component
re-render child component.
Enter fullscreen mode Exit fullscreen mode

即使子组件与状态完全无关。

现在,我们必须阻止子组件重新渲染。保留函数式组件,我们可以使用React.memo来实现这一点。子组件将变为:

import React, { memo } from "react";

const Child = memo(({ reset }) => {
   // same content as earlier
});

Enter fullscreen mode Exit fullscreen mode

如果没有第二个参数,memo将对 props 进行浅层比较:

if(prevProps !== props) {
  rerender();
} else {
  // don't
}

Enter fullscreen mode Exit fullscreen mode

现在您可以检查日志,发现它在父组件重新渲染时不会更新子组件。它只会使用以下日志更新父组件:

re-render parent component
Enter fullscreen mode Exit fullscreen mode

现在,需求已经取得进展,我们必须在Child组件内部放置一个用于计数的重置按钮。

这将使孩子折射到:

import React, { memo } from "react";

const Child = memo(({ reset }) => {
  console.log("re-render child component.")
  return (
    <div>
      <p>child component which resets count</p>
      <button onClick={reset}>Reset Count</button>
    </div>
  );
});

export default Child;
Enter fullscreen mode Exit fullscreen mode

对于重置功能,我们必须将父级折射为:

const Parent () => {
  const [count, setCount] = useState(0);
  console.log("re-render parent component");

  const resetCount = () => {
    setCount(0);
  };
  return (
    <main>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count=>(count+1))}>Increment</button>
      <Child reset={resetCount} />
    </main>
  )
}
Enter fullscreen mode Exit fullscreen mode

现在,您可以点击重置按钮将计数重置为 0。但是您会注意到,memo我们之前应用的魔法不再起作用。日志显示子组件和父组件都进行了重新渲染。
为什么会发生这种情况?

正如我们之前提到的,依赖于memo的引用相等性才能工作。但是该函数在的每次渲染中都会被创建,因此不再相同(即使它们本来就相同)。prevPropspropsresetCountParentprevPropsprops

现在,为了再次运用memo魔法,我们需要确保resetCount函数在每次渲染时不会不必要地重新创建Parent。这正是useCallback我们所需要的。

const resetCount = useCallback(() => {
    setCount(0);
}, [setCount]);
Enter fullscreen mode Exit fullscreen mode

useCallback重新渲染时始终返回相同的函数实例,并且仅当依赖项发生变化时才会刷新。请注意 的第二个参数useCallback,它与钩子非常相似useEffect,指的是应该触发钩子内函数重新初始化的依赖项useCallback

完成的演示:

从我的博客转载

延伸阅读:

  1. useCallback 文档
  2. 何时使用 useMemo 和 useCallback - Kent C Dodds
  3. 如何从 useCallback 中读取经常变化的值?
  4. 由于在渲染中创建函数,Hooks 是否很慢?
鏂囩珷鏉ユ簮锛�https://dev.to/boywithsilverwings/when-to-use-usecallback-dod
PREV
游戏开发和自我押注如何彻底改变了我的职业道路
NEXT
Schedule jobs with systemd timers, a cron alternative xcron/xcrontab