当前位置: 首页 > news >正文

React useCallback介绍(用来缓存函数的引用,避免每次渲染都重新创建函数)主要用于性能优化

文章目录

  • 🚀 React `useCallback` 深入理解与实战应用
    • 🌱 一、`useCallback` 是什么?
      • `useCallback` 是 React 提供的一个 Hook,用来**缓存函数的引用**。
      • 语法
      • 简而言之: **`useCallback` 返回一个记忆化的函数版本,只有当依赖改变时才会重新生成。**
    • ⚡ 二、为什么需要 `useCallback`
      • 📉 示例:未使用 `useCallback` 的问题
        • 代码
        • 分析
    • ⚙️ 三、使用 `useCallback` 解决
      • 代码
      • 分析
    • 🔍 四、`useCallback` 与 `useMemo` 的区别
    • 🧠 五、使用时机与注意事项
      • ✅ 适合使用的场景
        • 1. 子组件使用了 `React.memo`,并且接收函数作为 `props`;
        • 2. 函数在依赖变化前后逻辑相同;
        • 3. 函数的重新创建会导致不必要的渲染或副作用。
      • ⚠️ 不建议滥用
        • * `useCallback` 本身也有性能开销;
        • * 对普通函数(非 props 传递、不影响渲染)没必要使用;
        • * 若滥用,会增加代码复杂度且收益有限。
      • 🔧 建议
    • 💡 六、进阶技巧:搭配自定义 Hook 使用
    • 🧩 七、总结
    • 🎯 结语

🚀 React useCallback 深入理解与实战应用

在 React 开发中,性能优化始终是一个值得关注的话题。很多开发者在使用 Hooks 时都会遇到这样的疑问:

“为什么我需要用 useCallback?它到底解决了什么问题?什么时候该用它?”

本文将通过原理讲解 + 示例对比 + 实战技巧,帮助你彻底理解 React 的 useCallback


🌱 一、useCallback 是什么?

useCallback 是 React 提供的一个 Hook,用来缓存函数的引用

语法

const memoizedCallback = useCallback(() => {// 回调函数逻辑},[dep1, dep2]
);
  • 第一个参数:需要缓存的回调函数。
  • 第二个参数:依赖数组(当依赖变化时,才会重新创建函数)。

简而言之: useCallback 返回一个记忆化的函数版本,只有当依赖改变时才会重新生成。


⚡ 二、为什么需要 useCallback

在 React 中,每次组件重新渲染,所有内部定义的函数都会被重新创建
这在大多数场景下没问题,但在某些情况下会带来性能问题。

📉 示例:未使用 useCallback 的问题

代码
import React, { useState } from "react";"use client";import React, { useState } from "react";function Child({ onClick }: { onClick: () => void }) {console.log("🔄 Child render");return <button onClick={onClick}>点击子组件按钮</button>;
}const MemoChild = React.memo(Child);function App() {const [count, setCount] = useState(0);const handleClick = () => {console.log("Clicked");};return (<div><p>Count: {count}</p><div><button onClick={() => setCount(c => c + 1)}>加一</button></div><div><MemoChild onClick={handleClick} /></div></div>);
}export default App;

在这里插入图片描述

分析

运行这段代码后你会发现:

👉 即使我们只更新了 countMemoChild 仍然会重新渲染!

原因是:

  • 每次 App 渲染都会重新创建一个新的 handleClick 函数(不同内存地址);
  • 即使函数内容相同,但它们的引用不同
  • React.memo 判断 props 变化时发现 onClick 是一个新引用,于是重新渲染了子组件。

⚙️ 三、使用 useCallback 解决

代码

我们可以用 useCallback 来缓存这个函数引用:

const handleClick = useCallback(() => {console.log("Clicked");
}, []);

完整代码如下:

"use client";import React, { useState, useCallback } from "react";function Child({ onClick }: { onClick: () => void }) {console.log("🔄 Child render");return <button onClick={onClick}>点击子组件按钮</button>;
}const MemoChild = React.memo(Child);function App() {const [count, setCount] = useState(0);const handleClick = useCallback(() => {console.log("Clicked");}, []);return (<div><p>Count: {count}</p><div><button onClick={() => setCount(c => c + 1)}>加一</button></div><div><MemoChild onClick={handleClick} /></div></div>);
}export default App;

在这里插入图片描述

分析

✅ 现在,当我们点击“加一”按钮时:

  • 父组件会重新渲染;
  • handleClick 的引用未变;
  • 子组件 MemoChild 不再重新渲染。

性能优化达成 ✅


🔍 四、useCallbackuseMemo 的区别

Hook返回值主要用途
useCallback(fn, deps)返回函数缓存回调函数引用
useMemo(factory, deps)返回缓存计算结果

其实:

useCallback(fn, deps)useMemo(() => fn, deps)

但语义上更清晰:

  • 当你缓存的是函数,用 useCallback
  • 当你缓存的是计算结果,用 useMemo

🧠 五、使用时机与注意事项

✅ 适合使用的场景

1. 子组件使用了 React.memo,并且接收函数作为 props
2. 函数在依赖变化前后逻辑相同;
3. 函数的重新创建会导致不必要的渲染或副作用。

⚠️ 不建议滥用

* useCallback 本身也有性能开销;
* 对普通函数(非 props 传递、不影响渲染)没必要使用;
* 若滥用,会增加代码复杂度且收益有限。

🔧 建议

先写出正确的代码,再通过性能分析(如 React DevTools Profiler)决定是否引入 useCallback


💡 六、进阶技巧:搭配自定义 Hook 使用

在自定义 Hook 中使用 useCallback,可以有效避免无限循环:

function useFetch(url) {const [data, setData] = useState(null);const fetchData = useCallback(async () => {const res = await fetch(url);const json = await res.json();setData(json);}, [url]);useEffect(() => {fetchData();}, [fetchData]);return data;
}

这里若不加 useCallbackfetchData 每次都会变,useEffect 就会无限执行。

在这个代码中,fetchData 会因为 url 变化而变化。具体来说:

  • useCallback 的依赖项是 [url],所以当 url 发生变化时,fetchData 函数会重新创建
  • useEffect 的依赖项是 [fetchData],所以当 fetchData 变化时,useEffect 会重新执行
  • 当 useEffect 重新执行时,它会调用新的 fetchData 函数,从而触发新的 API 请求

🧩 七、总结

项目说明
作用缓存函数引用,避免子组件重复渲染
语法useCallback(fn, deps)
适用场景函数作为 props 传递给子组件时
常见搭配React.memouseEffect
不要滥用若无性能瓶颈,使用纯函数更简单

🎯 结语

useCallback 并不是一个“必须用”的 Hook,而是在特定性能场景下的优化工具
理解它的核心思路——函数引用的稳定性,才能在正确的地方使用它。

http://www.dtcms.com/a/515532.html

相关文章:

  • VUE工程化开发模式
  • 海口澄迈县建设局网站杭州萧山网络
  • 前端低代码开发工具的崛起与实践经验分享,从效率到可控性的平衡
  • 二、redis集群部署(3主3从)
  • Vue 生命周期详解
  • vue3调用ant-design-vue组件库的a-table组件
  • 手机网站开发软件南昌网站外包
  • 以图搜图随州网站seo诊断
  • java设计模式六、装饰器模式
  • 微信小程序隐藏滚动条多种方法教程
  • AWS DMS实现MySQL到Redshift的CDC增量数据复制方案
  • 王者重名生成查询抖音快手微信小程序看广告流量主开源
  • 旅游网站建设1000字软文范例800字
  • 网站搜索引擎友好性最近三天发生的重要新闻
  • Flink的checkpoint interval与mini-batch什么区别?
  • CADSoftTools发布两款重要更新:CAD VCL Multiplatform 16.2 与 CAD .NET 16全新发布
  • 【个人成长笔记】在本地Windows系统中如何正确使用adb pull命令,把Linux系统中的文件或文件夹复制到本地中(亲测有效)
  • 触摸未来2025-10-22:语序之困
  • 【滑动窗口与双指针】【定长滑窗】—1456. 定长子串中元音的最大数目
  • Flink 实验性特性把“已预分区”的 DataStream 重新解释为 KeyedStream
  • ADB -> 常用文件操作的组合命令
  • 网格系统网站济南网约车公司
  • 社区网站的推广方案手机写wordpress博客
  • 原子性、可见性和指令重排问题的根源
  • 什么是测试覆盖率?如何衡量?
  • 《宝可梦传说Z-A》下载 整合龙神Ryuinx、eden模拟器附金手指和存档 安卓手机PC版
  • 自动驾驶---基于安全走廊的端到端
  • 2025主流AI标书工具推荐,“闭眼选”高效生成投标文件
  • (22)100天python从入门到拿捏《【网络爬虫】网络基础与HTTP协议》
  • iis6建设网站叶梓 wordpress 主题