React useCallback 性能优化:原理、适用场景与最佳实践

望舒的头像
望舒
标签:
React 性能优化useCallbackReact Hooks函数组件React 重渲染

React 是一款流行的前端框架,而 Hooks 的出现让函数组件拥有了类似类组件的状态管理与副作用处理能力。在众多 Hooks 中,useCallback 是一个经常被提到的性能优化工具。那么,什么时候该用 useCallback?它真的能提高性能吗? 本文将结合 React 官方文档 与实战经验,带你全面认识 useCallback 的作用与使用要点。


什么是 useCallback

useCallback 是 React 提供的一个 Hook,用来缓存函数。当组件重新渲染时,如果依赖项不变,React 会返回之前缓存的同一个函数引用,而不是创建一个新的函数。

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

⚡️ 本质: useCallback(fn, deps) 相当于 useMemo(() => fn, deps)


为什么要用 useCallback

在 React 中,组件每次渲染时,都会重新定义函数。如果这些函数被当作 props 传给子组件,就可能触发子组件的不必要重渲染

举例:

复制
const Parent = () => {
  const handleClick = () => console.log('clicked');
  return <Child onClick={handleClick} />;
};

每次 Parent 渲染时,handleClick 都是一个新函数,即使函数体完全相同,Child 如果是 React.memo 包裹的,也会检测到 props 变了,从而重新渲染。

这时就可以用 useCallback

复制
const handleClick = useCallback(() => console.log('clicked'), []);

这样,如果依赖项不变(这里是空数组),每次渲染都能返回相同的函数引用,避免不必要的子组件重渲染。


适用场景:什么时候该用 useCallback

官方建议:只在需要稳定函数引用时使用。常见场景包括:

  • 子组件使用了 React.memouseMemo 且依赖父组件传入的函数。
  • 函数作为依赖项传入其他 Hook(如 useEffect)。
  • 大量渲染列表时,避免因函数变化导致子项不必要的重渲染。

不该用的场景:

  • 简单组件或无性能瓶颈的页面。
  • 函数体简单,重新创建开销几乎可以忽略。

记住: 过度使用 useCallback 也会带来性能负担,因为 React 要记住并对比依赖项。


实战案例:配合 React.memo 提升性能

假设有一个列表,每一项都有一个点击回调:

复制
const List = ({ items, onItemClick }) => {
  return items.map(item => (
    <ListItem key={item.id} item={item} onClick={onItemClick} />
  ));
};

const ListItem = React.memo(({ item, onClick }) => {
  console.log('render', item.id);
  return <div onClick={() => onClick(item.id)}>{item.name}</div>;
});

父组件中:

复制
const App = () => {
  const [count, setCount] = useState(0);

  const handleItemClick = useCallback((id) => {
    console.log('Clicked item', id);
  }, []);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Add Count</button>
      <List items={data} onItemClick={handleItemClick} />
    </>
  );
};

这里点击按钮只会改变 count,由于 handleItemClick 是稳定的引用,不会导致 ListItem 重渲染。


最佳实践与小结

  • 只在需要稳定函数引用时使用 useCallback
  • 先用原生写法,如果出现性能瓶颈,再配合 React.memo 做优化。
  • 对复杂回调或依赖较多的回调,要认真管理依赖数组,防止 bug。
  • 不要盲目用 useCallback,否则适得其反。

结语

useCallback 是 React 性能优化中的重要工具,但它不是银弹。只有在合适的场景下使用,才能真正减少不必要的渲染、提升用户体验。更多详情可以参考 React 官方文档

作者:https://blog.xn--rpv331d.com/望舒

链接:https://blog.xn--rpv331d.com/望舒/blog/90

转载注意保留文章出处...

‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌‌​‌​‌‌‌‌​​​​‌​‌‌​‌​‌​​‌‌‌​​‌​‌‌​​​​​‌‌​‌​‌‌​‌​‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌​​‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌‌‌‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌​‌‌‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌​‌‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​​‌​‌‌​‌‌‌‌​​​‌‌​​​‌‌​‌‌‌‌‌‌‌‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌‌‌‌‌​‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌‌‌‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌​‌‌‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌​‌‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​​‌​‌‌​‌‌‌‌​​​‌‌​​​‌‌​‌‌‌‌‌‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌​‌‌​​‌‌‌​‌‌​‌‌‌​‌​​‌‌​​​​‌​​​​​​​​​​​‌‌​‌​‌‌​‌​‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌​​‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌‌‌‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌​‌‌‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌​‌‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​​‌​‌‌​‌‌‌‌​​​‌‌​​​‌‌​‌‌‌‌‌‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​‌‌‌‌‌‌​‌​‌‌​‌‌‌​‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌‌‌‌‌​‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌‌‌‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌‌‌‌‌‌​‌​‌‌​‌‌‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌​‌​‌​‌‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​​‌​‌‌​‌‌‌‌​​​‌‌​​​‌‌​‌‌‌‌‌‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌‌​‌​‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌​‌‌‌‌‌‌​‌​‌‌​‌‌‌​‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌​‌‌‌‌‌‌‌‌‌‌​​‌​‌‌‌‌​‌‌‌‌‌‌‌​‌‌​‌​​‌‌‌‌‌‌‌‌‌​​‌​‌​‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌‌‌‌‌‌​‌​‌‌‌‌​‌‌‌​‌‌‌‌‌‌​‌​​‌​‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌‌‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌​​‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌​​‌​‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌​​‌​‌‌‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌‌‌​​​​‌‌​​​​​‌‌‌‌‌​​​‌‌‌​​​​​​‌‌‌‌‌‌​​‌​​​​‌‌‌​​‌​‌‌‌​‌​‌‌‌​​​​‌‌‌​‌​‌‌‌‌​​​​​​​​‌‌‌​‌‌​‌‌​‌​​​‌‌​‌‌​​​​‌‌‌​​​​​​‌​‌‌​​​​​​‌‌‌​​​‌‌‌‌‌‌‌​‌‌‌​‌​​​​‌‌‌​​‌‌​​​​‌​‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌‌‌‌‌​‌‌‌‌‌‌​‌​​‌‌‌‌‌​‌‌‌​‌‌​‌‌​‌​‌‌‌‌‌‌‌‌​‌​‌​‌‌‌‌‌‌​‌‌‌‌‌‌​‌‌​‌‌‌‌
No data