什么时候应该用useCallback

1. 将函数作为属性传递给子组件

这是使用 useCallback 最常见且最重要的场景。

当父组件重新渲染时,它内部声明的所有函数都会被重新创建。如果你将这些新创建的函数作为 props 传递给子组件,即使函数的功能没有改变,子组件也会因为接收到新的 prop 引用而重新渲染。

这对于使用了 React.memo 的子组件尤其重要。React.memo 旨在通过浅层比较 props 来防止不必要的重新渲染。然而,如果传递的函数 prop 每次都是一个新的引用,React.memo 的优化就会失效,因为它会认为 props 已经改变了。

useCallback 能够确保在它的依赖项没有变化时,函数引用保持不变,从而让 React.memo 正常工作。

javascript 复制代码
import React, { useState, useCallback } from 'react';

// 使用 React.memo 包装子组件,以防止不必要的重新渲染
const ButtonComponent = React.memo(({ onClick }) => {
  console.log('按钮组件已渲染');
  return <button onClick={onClick}>点击我</button>;
});

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

  // 不使用 useCallback 的情况:
  // const handleClick = () => setCount(count + 1);

  // 使用 useCallback 缓存函数,只有在依赖项([])改变时才重新创建。
  // 由于依赖项为空,此函数只在组件首次渲染时创建一次。
  const handleClick = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);

  console.log('父组件已渲染');

  return (
    <div>
      <p>计数: {count}</p>
      {/* 将缓存的函数传递给子组件 */}
      <ButtonComponent onClick={handleClick} />
    </div>
  );
}

2. 作为其他Hook的依赖项

如果一个函数被用作 useEffectuseMemo 或另一个 useCallback 的依赖项,那么你也应该使用 useCallback

场景:作为 useEffect 的依赖项

如果不使用 useCallback,每次父组件渲染时,这个函数都会被重新创建,导致 useEffect 认为它的依赖项发生了变化,从而重复执行副作用(例如,重复发起网络请求)。

javascript 复制代码
import React, { useState, useEffect, useCallback } from 'react';

function MyDataFetcher() {
  const [data, setData] = useState(null);

  // 使用 useCallback 确保 fetchData 的引用是稳定的
  const fetchData = useCallback(async () => {
    try {
      const response = await fetch('https://api.example.com/data');
      const result = await response.json();
      setData(result);
    } catch (error) {
      console.error("数据获取失败", error);
    }
  }, []); // 由于依赖项为空,该函数在组件生命周期内只创建一次

  useEffect(() => {
    // 依赖项是 fetchData 函数,因此它的引用必须保持稳定
    fetchData();
  }, [fetchData]); // 如果没有 useCallback,这里会造成无限循环

  return <div>{data ? JSON.stringify(data) : '正在加载...'}</div>;
}

以上代码,可以如何优化,useEffect的第二个参数为空数组不行吗?

请看链接:juejin.cn/post/754104...

结论

useCallback 的核心价值在于 :在依赖项不改变的前提下,保持函数引用的稳定性

你不需要在每个函数上都使用 useCallback。只有当你遇到以下情况时,才应该考虑使用它:

  • 将函数作为 props 传递给一个使用 React.memo 优化的子组件。
  • 将函数作为 useEffectuseMemo 的依赖项。

在大多数简单组件中,重新创建函数引用的开销非常小,并不会对性能造成明显影响。过度使用 useCallback 反而会增加代码的复杂性。因此,请有针对性地使用它,将其视为一个性能优化工具,而非常规开发模式。

相关推荐
数据知道2 小时前
AES 加密实战——模式选择(ECB/CBC/GCM)与安全陷阱
前端·网络·安全
一夜枫林3 小时前
vue实现scroll-view上下滑动右侧左右滑动
前端·javascript·vue.js
苏三的开发日记3 小时前
npm EPERM:无法写入 `.npmrc` 的排查与解决
前端
YWL3 小时前
OpenLayers地图分享:URL参数同步+分享链接生成,让用户一键分享地图视角
前端·javascript·vue·openlayers
枫叶梨花4 小时前
Electrobun透明窗口在Windows上的输入穿透排查
前端·electron·bun
云上工程笔记5 小时前
AstraFlow + React/Vite:如何用自然语言开发并部署一个 AI 咖啡网站原型
前端·人工智能·react.js
Q一件事5 小时前
ArcGIS中TypeError: can‘t multiply sequence by non-int of type ‘str‘错误
前端·javascript·arcgis
美狐美颜SDK开放平台5 小时前
从视频处理到实时渲染:直播APP中视频美颜SDK的关键技术解析
前端·人工智能·架构·实时互动·音视频·视频美颜sdk
yume_sibai6 小时前
ES6 核心知识点完全总结(变量 + 箭头函数 + 解构 + Promise + 模块化)
前端·ecmascript·es6
Moment6 小时前
为什么市面上的 coding agent 大多数都基于Nodejs?
前端·后端·面试