React useCallback如何使其性能最大化?
前言
React中最让人畅谈的就是其带来的灵活性,可以说写起来非常的舒服。但是也就是它的灵活性太强,往往让我们忽略了很多细节的地方,而就是这些细节的东西能进行优化,减小我们的性能开销。可以说刚学React和工作几年后写React的代码真的是完全不一样。
废话不多说了,今天带大家来了解useCallback有哪些细节之处可以让我们做进一步的性能优化。
如果你不太了解useCallback,可以看看我这篇文章正确使用useCallback的姿势
没做优化前的代码
简单的一个结构,父子组件,子组件接收父组件触发数字改变的函数。
父组件
import React, { memo, useState } from "react";
import Son from "../commponet/Son";const Optimize = memo(() => {console.log("Optimize 组件重新渲染了");const [count, setcount] = useState(10);const [isshow, setisshow] = useState(true);// 未优化const addNum = () => {setcount(count + 10);};const changeShow = () => {setisshow(!isshow);};return (<div><h2>Optimize</h2><h3>count:{count}---isshow:{isshow.toString()}</h3><button onClick={(e) => addNum()}>add+10</button><button onClick={(e) => changeShow()}>changeshow</button><Son addNum={addNum} /></div>);
});export default Optimize;
子组件
import React, { memo } from "react";interface Props {count?: number;addNum: Function;
}const Son = memo((props: Props) => {const { addNum } = props;console.log("Son 组件重新渲染了");return (<div><h2>Son</h2><button onClick={(e) => addNum()}>click</button></div>);
});export default Son;
测试—结论
三个按钮都点击一遍,发现

原因不用多说了吧,看过我之前那篇文章的都懂,下面进行进一步优化。
第一次优化
使用useCallback来进行优化
父组件只贴一些关键代码
子组件代码未改变,这里就不贴了
// 第一次优化const addNum = useCallback(() => {setcount(count + 10);}, [count]);const changeShow = useCallback(() => {setisshow(!isshow);}, [isshow]);
测试—结论
前两次点击都是触发 addNum 最后一次点击触发 changeShow

一般优化都只是到此为止,可是我们想想,子组件中并未用到我们的count 只是接收了addNum函数,如果我们能只让父组件进行更新子组件不更新不才是最理想的状态吗?
最终优化
首先要搞明白为什么子组件会更新?那是因为每次count更新时,重新生成一个新函数,引用地址发生了变化,子组件发现前后;两次地址不一样所以进行了更新。那能不能让其始终用最开始的函数地址呢?
const changeShow = useCallback(() => {setisshow(!isshow);}, [isshow]);// 第二次优化const countRef = useRef(count);countRef.current = count;const addNum = useCallback(() => {setcount(countRef.current + 10);}, []);
使用空数组代表我们一直不会改变函数地址,用的是最开始的那个函数
那如何修改值呢?这里巧妙用useRef来帮助我们记录每次更新的值
为什么使用useRef? 因为useRef是贯穿整个生命周期的,每次render重新执行时useRef都是同一个对象。不信?那我们测试测试呗。
import React, { memo, useCallback, useRef, useState } from "react";
import Son from "../commponet/Son";let obj: any = null;
const Optimize = memo(() => {const aaa = useRef();console.log(obj === aaa);obj = aaa;console.log("Optimize 组件重新渲染了");const [count, setcount] = useState(10);const [isshow, setisshow] = useState(true);// 未优化const addNum = () => {setcount(count + 10);};const changeShow = () => {setisshow(!isshow);};return (<div><h2>Optimize</h2><h3>count:{count}---isshow:{isshow.toString()}</h3><button onClick={(e) => addNum()}>add+10</button><button onClick={(e) => changeShow()}>changeshow</button></div>);
});export default Optimize;

可以看到确实是同一个对象的,如果我们采用之前的count 或者自己定义一个新对象就会陷入闭包陷阱了!
它们都会保存最开始的值的引用,后续render更新的是新地址,不会被其引用,感兴趣的可以去测试测试,这里就不测试了。
// 用普通对象和之前值是否可行?闭包陷阱const countRef = { current: count };countRef.current = count;const addNum = useCallback(() => {// setcount(countRef.current + 10);setcount(count + 10);}, []);
测试—结论
三个按钮都点击了一次,发现都只是父组件更新了

总结
这里并不是说所有的 useCallback 都要进行这样处理,其实是没必要的。我们要根据实际情况来分析,就比如我们上面这个例子那是建立在子组件没有依赖父组件的count数据,所以我们可以选择只渲染父组件就可以,若是子组件也用到了count数据则推荐使用第一次优化即可。
一键三连,关注不迷路!

相关文章:
React useCallback如何使其性能最大化?
前言 React中最让人畅谈的就是其带来的灵活性,可以说写起来非常的舒服。但是也就是它的灵活性太强,往往让我们忽略了很多细节的地方,而就是这些细节的东西能进行优化,减小我们的性能开销。可以说刚学React和工作几年后写React的代…...
长尾关键词使用方法,通过什么方式挖掘长尾关键词?
当你在搜索引擎的搜索栏中输入有关如何使用长尾关键词的查询时,你可能希望有简单快捷的方式出现在搜索结果中,可以帮助你更好地应用seo。 不过,这里要记住一件事:SEO 策略只会为你的网站带来流量;在你的产品良好之前&a…...
【网络编程套接字(一)】
网络编程套接字(一)理解源IP地址和目的IP地址理解源MAC地址和目的MAC地址理解源端口号和目的端口号PORT VS PID认识TCP协议和UDP协议网络字节序socket编程接口socket常见APIsockaddr结构简单的UDP网络程序服务端创建套接字服务端绑定字符串IP VS 整数IP客…...
shell脚本入门
实习的时候第一个月的考核就是如何部署一个云资源,当时走的捷径(杠杠的搜索能力hhhh)找到了一个shell脚本一键部署,后来被leader问起来就如实说了,leader问有没有看懂shell脚本中的逻辑……(没有࿰…...
【经典蓝牙】 蓝牙HFP层协议分析
HFP 概述 HFP概念介绍 HFP(Hands-Free Profile), 是蓝牙免提协议, 可以让蓝牙设备对对端蓝牙设备的通话进行控制,例如蓝牙耳机控制手机通话的接听、 挂断、 拒接、 语音拨号等。HFP中蓝牙两端的数据交互是通过定义好的AT指令来通讯的。 &am…...
互联网摸鱼日报(2023-02-26)
互联网摸鱼日报(2023-02-26) InfoQ 热门话题 迁移工具 Air2phin 宣布开源,2 步迁移 Airflow 至 Dolphinscheduler 专访奇安信董国伟博士:目前开源安全的现状并不乐观,但其重要性已成各方共识 专访Brian Behlendorf&…...
关于程序员中年危机的一个真实案例
关于中年危机,网上已经有了各种各样的解读。但是,这两天一个学员跟我简单几句聊天,却触发了对于中年危机的另一种思考。如果你曾经也有点迷茫,或许你可以稍微花几分钟看下这个故事。 一、无奈的故事 39岁还出来面试&#x…...
【fly-iot飞凡物联】(2):如何从0打造自己的物联网平台,使用开源的技术栈搭建一个高性能的物联网平台,目前在设计阶段。
目录前言1,fly-iot 飞凡物联2,mqtt-broker 服务3, 管理后台产品/设备设计4,数据存储目前使用mysql,消息存储到influxdb中5,规则引擎使用 ekuiper6, 总结和其他的想法前言 本文的原文连接是: https://blog.csdn.net/freewebsys/article/detail…...
Hadoop MapReduce
目录1.1 MapReduce介绍1.2 MapReduce优缺点MapReduce实例进程阶段组成1.3 Hadoop MapReduce官方示例案例:评估圆周率π(PI)的值案例:wordcount单词词频统计1.4 Map阶段执行流程1.5 Reduce阶段执行流程1.6 Shuffle机制1.1 MapReduc…...
时间复杂度和空间复杂度详解
有一堆数据需要排序,A要使用快速排序,B要使用堆排序,A认为自己的代码更高效,B也认为自己的代码更高效,在这种情况下,怎么来判断谁的代码更好一点呢?这时候就有了时间复杂度和空间复杂度。 目录 …...
【C++】面向对象---封装
【C】面向对象—封装 1.封装的意义 封装是C面向对象三大特性之一 封装的意义: 将属性和行为作为一个整体,表现生活的事物将属性和行为加以权限控制 封装意义一: 在设计类的时候,属性和行为写在一起,表现事物 语…...
Docker简介
一、介绍容器虚拟化技术(带环境安装的一种解决方案)打破程序即应用的观念,透过镜像image将作业系统核心除外,运用应用程序所需要的运行环境,由上而下打包,达到应用程序跨平台间的无缝接轨运作。Docker是基于…...
量化学习(一)数据获取
试验环境 windows10 AnacondaPyCharm(小白参考文章:https://coderx.com.cn/?p14) VM中安装MySQL5.7(设置utf8及相应配置优化) 关于复权 小白参考文章:https://zhuanlan.zhihu.com/p/469820288 数据来源 AK…...
java并发编程讨论:锁的选择
java并发编程 线程堆栈大小 单线程的堆栈大小默认为1M,1000个线程内存就占了1G。所以,受制于内存上限,单纯依靠多线程难以支持大量任务并发。 上下文切换开销 ReentrantLock 2个线程交替自增一个共享变量,使用ReentrantLock&…...
大数据框架之Hadoop:MapReduce(三)MapReduce框架原理——ReduceTask工作机制
1、ReduceTask工作机制 ReduceTask工作机制,如下图所示。 (1)Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直…...
Nginx的介绍、安装与常用命令
前言:传统结构上(如下图所示)我们只会部署一台服务器用来跑服务,在并发量小,用户访问少的情况下基本够用但随着用户访问的越来越多,并发量慢慢增多了,这时候一台服务器已经不能满足我们了,需要我们增加服务…...
less基础
一、less介绍 1、介绍 是css预处理语言,让css更强大,可以实现在less里面定义变量函数运算等 2、less默认浏览器不识别 less转成csS (框架: less/sass 框架的内置了转码less-css) 3、使用语法 1.创建less文件xxx.less 后缀.less 2. less编译成css 再引入…...
电子统计台账:海量数据中导入特定行,极力减少键盘编辑工作量
1 前言从事企业统计工作的小伙伴,本来已经够忙的了,现在又要加上什么电子台账这种鬼任务,而且居然还要每月来一次,简直不能忍。如果非要捏着鼻子忍了,那么有什么办法,减轻工作量?2 问题的提出有…...
ChatGPT是如何训练得到的?通俗讲解
首先声明喔,我是没有任何人工智能基础的小白,不会涉及算法和底层原理。 我依照我自己的简易理解,总结出了ChatGPT是怎么训练得到的,非计算机专业的同学也应该能看懂。看完后训练自己的min-ChatGPT应该没问题 希望大牛如果看到这…...
刷题28-有效的变位词
32-有效的变位词 解题思路: 注意变位词的条件,当两个字符串完全相等或者长度不等时,就不是变位词。 把字符串中的字符映射成整型数组,统计每个字符出现的次数 注意数组怎么初始化: int [] s1new int[26]代码如下&a…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
