如何使用useCallback优化React性能?

JS 基础知识回顾

Javascript中,函数是一种引用类型的变量,即存放的并非真实的值,而是引用值,类似于C语言中的指针类型。

当我们在JavaScript中, 每次定义函数(如 () => {}function() {})时,都会在内存中创建一个新的对象。例如:

Javascript 复制代码
const a = () => {};
const b = () => {};
console.log(a === b); // false(两个不同的函数对象)
  • 关键点 : 函数a和函数b的内容虽然完全相同,但是它们各自创建,代表着内存中的不同位置
  • 结果 : 函数a和函数b实际的值(类似于指针)不一样,因此将它们两相比较的结果就是false

React中函数引用的频繁变化

React中,函数式组件本身就是一个 JavaScript 函数,每次重新渲染时,整个函数体会从头到尾执行一次,包括内部的所有变量和函数声明,组件内部定义的函数会被重新创建,使用新的内存地址。

当父组件将函数通过 props 传递给子组件时,即使函数内容未变,子组件也会因 props 的引用不同而触发重新渲染。

例如,当我们在组件内部定义一个函数时(以 handleClick为例),它本质上是这样工作的:

JSX 复制代码
const Parent = () => {
  // 每次 Parent 渲染时,都会重新声明并创建一个新的 handleClick 函数
  const handleClick = () => {
    console.log("Click");
  };

  return <Child onClick={handleClick} />;
};
  • 关键点:函数组件本身是一个 JavaScript 函数,每次重新渲染时,整个函数体会从头到尾执行一次,包括内部的所有变量和函数声明。
  • 结果handleClick 会被重新创建为一个新的函数对象(新的内存地址),即使函数内容没有变化。不仅如此,每当父组件重新渲染时,Child 就会重新渲染,因为 onClick 的引用变了。

如何解决?用useCallback缓存函数

如果有一种方法,能通过缓存函数,仅在某些条件下(比如依赖项变化时)才生成新函数 ,否则复用上一次的函数引用,那么就可以避免重复创建相同内容的函数引用 。可惜,这只是在白日做梦o (T ヘ To)

事实上,React 中的useCallback钩子就可以帮助我们实现刚才的想法。 通过 useCallback 缓存函数,可以避免每次渲染时重新创建函数:

JSX 复制代码
const Parent = () => {
  // ✅ 用 useCallback 缓存函数,依赖项为空数组(函数只创建一次)
  const handleClick = useCallback(() => {
    console.log("Click");
  }, []);

  return <Child onClick={handleClick} />;
};
  • 关键点handleClick 的引用保持不变,子组件 Childprops 不会发生变化。
  • 结果 :父组件更新 count 时,Child 不会因 onClick 引用变化而重新渲染,从而解决函数引用频繁变化带来的性能问题。

总结

  • 根本问题:函数组件每次渲染时都会重新执行,导致内部函数重新声明。
  • 关键影响:函数引用变化会触发子组件不必要的渲染(即使内容相同)。
  • 解决方案 :用 useCallback 缓存函数,仅在依赖项变化时重新创建函数。

在实际使用时,我们需要清楚何时需要优化函数引用,何时可以直接定义函数。

注意,不要滥用 useCallback,只在必要时使用(如性能敏感场景或子组件依赖函数引用时)。

相关推荐
king王一帅1 小时前
Incremark Solid 版本上线:Vue/React/Svelte/Solid 四大框架,统一体验
前端·javascript·人工智能
智航GIS6 小时前
10.4 Selenium:Web 自动化测试框架
前端·python·selenium·测试工具
前端工作日常6 小时前
我学习到的A2UI概念
前端
徐同保7 小时前
为什么修改 .gitignore 后还能提交
前端
一只小bit7 小时前
Qt 常用控件详解:按钮类 / 显示类 / 输入类属性、信号与实战示例
前端·c++·qt·gui
Mr -老鬼7 小时前
前端静态路由与动态路由:全维度总结与实践指南
前端
颜酱8 小时前
前端必备动态规划的10道经典题目
前端·后端·算法
wen__xvn8 小时前
代码随想录算法训练营DAY10第五章 栈与队列part01
java·前端·算法
大怪v9 小时前
前端佬们!!AI大势已来,未来的上限取决你的独特气质!恭请批阅!!
前端·程序员·ai编程
Mr -老鬼9 小时前
功能需求对前后端技术选型的横向建议
开发语言·前端·后端·前端框架