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

React Hooks UseCallback

  开发环境:React Native + Taro + Typescript
useCallback的用途,主要用于性能优化:
1 避免不必要的子组件重渲染:当父组件重渲染时,如果传递给子组件的函数每次都是新创建的,即使子组件使用了 React.memo,也会导致子组件重新渲染。
2 作为其他 Hook 的依赖项:当函数被用作 useEffect、useMemo 或其他 Hook 的依赖项时,使用 useCallback 可以确保函数引用稳定,避免不必要的 effect 执行。
3 记忆化函数:对于创建成本较高的函数,使用 useCallback 可以避免在每次渲染时都重新创建。

    useCallback的优势:
1 性能优化:通过缓存函数实例,减少不必要的重渲染和函数创建,提高应用性能。
2 避免无限循环:在 useEffect 中使用函数时,如果函数没有使用 useCallback 包装,可能会导致无限重渲染。
3 稳定的函数引用:确保在依赖项不变的情况下,函数引用保持不变,这对于优化子组件渲染特别有用。

    使用时的注意事项:
1 不要过度使用:只有在确实需要优化性能时才使用 useCallback,因为useCallback本身也有性能开销。
2 正确设置依赖数组:确保依赖数组中包含所有在函数内部使用且可能变化的值,否则可能导致闭包问题。
3 与 React.memo 配合使用:useCallback 通常与 React.memo 一起使用才能发挥最大效果。

        下面是父组件:UseCallback

import React, { useState, useCallback, useEffect } from 'react'
import { View, Text, Button, ScrollView } from '@tarojs/components'
import styles from './plant.module.scss'
import Strawberry from './UseCallbackSub'const PlantManager: React.FC = ()=>{useEffect(()=>{console.log("父组件:useEffect, 组件重渲染!!!")})// 草本植物科目数量 初始化const [subjectNum, setSubjectNum] = useState(0)// 蔷薇科的植物或水果的颜色 初始化const [rosaceaeColor, setrosaceaeColor] = useState('green')// 蔷薇科的植物或水果size大小 初始化const [rosaceaeSize, setRosaceaeSize] = useState(5)// 蔷薇科植物或水果的颜色 改变次数,需要改变草莓颜色时,需要在此加一const [changeColorNum, setChangeColorNum] = useState(0)// 没有使用useCallback的函数,每次渲染都会创建新的函数实例const handleInrement = () => {console.log('父组件 handleInrement')// setSubjectNum(preSubjectNum => preSubjectNum + 1);}// 使用useCallback缓存函数,同样改变subjectNum的值const handleUseCallbackChangeSubjectNum = useCallback(()=>{console.log('父组件 handleUseCallbackChangeSubjectNum')// setSubjectNum(preSubjectNum => preSubjectNum + 1);}, []); //这里的依赖数组为空,是因为setSubjectNum是稳定的// 使用useCallback缓存函数,并带有依赖项// 改变子组件中草莓的颜色,并查看子组件渲染的时机与次数const handleChangeRosaceaeColor = useCallback(()=>{const color = rosaceaeColor === 'green' ? 'green' : 'red'setrosaceaeColor(color)}, [changeColorNum])const handleChangeColorNum = useCallback(()=>{setChangeColorNum(preNum => preNum + 1)}, [])// 使用useCallback缓存函数,没有依赖项// 改变子组件中草莓的size大小,并查看子组件渲染的时机与次数const handleChangeRosaceaeSize = useCallback(()=>{setRosaceaeSize(preSize => preSize + 1)}, [])return (<ScrollViewscrollYscrollWithAnimationclassName={styles.scroll}style={{height: '40vh',}}><View className={styles.container}><View className={styles.showTextBox}><Text>草本植物的数量 subjectNum = {subjectNum}</Text><Text>蔷薇科植物颜色需要改变的次数 = {changeColorNum}</Text><Strawberry color={rosaceaeColor}increment={handleInrement}changeSubjectNum={handleUseCallbackChangeSubjectNum}size={rosaceaeSize}></Strawberry></View><View className={styles.showTextBox}><Text className={styles.showText}>使用useCallback带有依赖项,改变子组件中草莓的颜色</Text><Button onClick={handleChangeRosaceaeColor} className={styles.actionBox} >改变子组件的草莓颜色</Button><Button onClick={handleChangeColorNum} className={styles.actionBox}>需要改变蔷薇科植物颜色时,给changeColorNum加一</Button></View><View className={styles.showTextBox}><Text className={styles.showText}>使用useCallback没有带依赖项,改变子组件中草莓size大小</Text><Button className={styles.actionBox} onClick={handleChangeRosaceaeSize}>改变子组件草莓的size</Button></View></View></ScrollView>)
}export default PlantManager

        下面是子组件:UseCallbackSub

import React, { useEffect, memo } from 'react'
import { View, Text, Button } from '@tarojs/components'
import styles from './plant.module.scss'interface StrawberryProps {color: stringsize: numberincrement: ()=>voidchangeSubjectNum: ()=>void
}// 定义一个子组件,用于查看子组件的更新状态const Strawberry: React.FC<StrawberryProps> = (props)=>{const { increment, changeSubjectNum } = props;useEffect(()=>{console.log("子组件重新渲染更新!!!")console.log("当前草莓的颜色: ", props.color);})return (<View className={styles.berryBox}><Text className={styles.showText}>子组件 草莓</Text><Text className={styles.berryTxt} style={{backgroundColor: props.color,}}>草莓的颜色</Text><Text className={styles.berryTxt}>草莓的大小size = {props.size}</Text><View className={styles.showTextBox}><Text className={styles.showText}>普通函数,没有使用useCallback缓存, 每次都会重新创建</Text><Button className={styles.actionBox} onClick={increment}>增加草本植物的数量</Button></View><View className={styles.showTextBox}><Text className={styles.showText}>使用useCallback缓存函数</Text><Button className={styles.actionBox} onClick={changeSubjectNum}>增加草本植物的数量</Button></View></View>)}// export default Strawberry;
export default memo(Strawberry);

        下面的文件是样式:

.container {margin-top: 30px;margin-bottom: 50px;margin-left: 15px;margin-right: 15px;padding: 20px;background-color: darkgrey;
}.scroll {margin-top: 30px;margin-bottom: 30px;margin-left: 15px;margin-right: 15px;
}.showTextBox {background-color: antiquewhite;padding: 10px;text-align: center;margin-bottom: 30px;
}.showText {padding: 20px;text-align: center;margin-top: 18px;background-color: cornflowerblue;
}.actionBox {background-color: aquamarine;padding: 20px;margin-top: 20px;
}.actionContainer {padding: 15px;margin-top: 30px;
}.berryBox {background-color: darksalmon;padding: 30px;
}.berryTxt {padding-left: 80px;padding-right: 80px;padding-top: 30px;padding-bottom: 30px;margin-bottom: 35px;
}

http://www.xdnf.cn/news/20358.html

相关文章:

  • Docker Registry 实现原理、适用场景、常用操作及搭建详解
  • CRYPT32!CryptMsgUpdate函数分析两次CRYPT32!PkiAsn1Decode的作用
  • Linux之Docker虚拟化技术(四)
  • 解决Vue Canvas组件在高DPR屏幕上的绘制偏移和区域缩放问题
  • Process Explorer 学习笔记(第三章3.2.1):主窗口与进程列表详解
  • 9.5C++作业
  • Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.2 Spring Security集成
  • 使用PyTorch构建卷积神经网络(CNN)实现CIFAR-10图像分类
  • 1688 商品详情抓取 API 接口接入秘籍:轻松实现数据获取
  • LeetCode Hot 100 第11天
  • 微前端架构:解构前端巨石应用的艺术
  • 【Android】制造一个ANR并进行简单分析
  • Kotlin中抽象类和开放类
  • 《从报错到运行:STM32G4 工程在 Keil 中的头文件配置与调试实战》
  • CRYPT32!ASN1Dec_SignedDataWithBlobs函数分析之CRYPT32!ASN1Dec_AttributesNC的作用是得到三个证书
  • 垃圾回收算法详解
  • 《sklearn机器学习——回归指标2》
  • Java内部类
  • 再读强化学习(动态规划)
  • 时隔4年麒麟重新登场!华为这8.8英寸新「手机」给我看麻了
  • 《Ceph集群数据同步异常的根因突破与恢复实践》
  • 深入剖析RocketMQ分布式消息架构:从入门到精通的技术全景解析
  • Ubuntu 文件权限管理
  • 【正则表达式】选择(Alternation)和分支 (Branching)在正则表达式中的使用
  • MySQL InnoDB 的锁机制
  • Chrome 插件开发入门:打造个性化浏览器扩展
  • 神经网络|(十八)概率论基础知识-伽马函数·下
  • Follow 幂如何刷屏?拆解淘宝闪购×杨幂的情绪共振品牌营销
  • Doris 消费kafka消息
  • 通过PXE的方式实现Ubuntu 24.04 自动安装