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

useCallback和forwardRef的联合使用

文章目录

  • 一、useCallback
  • 二、forwardRef

总结了useCallback、forwardRef中的deps,以及操作子组建时会遇到数据流不同步的问题

一、useCallback

  • useCallback可以缓存函数,这样避免组建更新导致的函数重建;
  • useCallback在函数更新以后会在deps中对比每一项,有值的变化,会更新函数中依赖项的最新值,重新创建函数;
  • 如果没有触发deps,那么这个函数不会重新创建,并且函数内使用的state值也不会变化(尤其是累加,赋值);
  • 但是useRef变量永远是最新值,一般不需要去依赖useRef值,除非他的值变化了需要去刷新函数
  • 没有deps,如果只是使用setState消息队列如:setCount((count) => count + 1),则可以拿到最值,但是也只是在函数内部使用;set函数外部依旧不会拿到最新值
  • 函数也拥有地址,会被deps捕获识别;useCallback可以缓存函数,即函数地址不会更改
import { Col, message, Row, Space } from "antd";
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from "react";export default function ParentRef() {const countRef = useRef(0);const [count, setCount] = useState(0);const [name, setName] = useState(0);// 每一次组建更新,都会生成新的函数,addFunc在其他hooks都deps中都会被识别成值产生变化const addFunc = () => {setCount(count + 1);countRef.current = countRef.current + 1;};// useCallback 中的 deps 变化,才会触发重新生成新的函数;// 没有触发deps更新,也可以调用,但是其中的依赖项使用之前的快照值(set队列函数会显示正常)const handleClick = useCallback(() => {setCount(count + 1); // 引发组件更新countRef.current = countRef.current + 1; // 不会引发组件更新;值的对比// deps 数值或者引用地址的变化,都会触发重新调用生成新的handle}, [countRef.current]);return (<div><p>Parent</p><button onClick={handleClick}>Focus Input</button><hr /></div>);
}

二、forwardRef

  • forwardRef控制子组建,useImperativeHandle暴露子组建属性;在页面代码拆分以后,组件逻辑分布分散,使用forwardRef可以快速操作子组建完成动作,而避开了传参的麻烦;
  • useImperativeHandle也有deps依赖,类似于useCallback的deps,只有deps依赖变化,才会重新创建createHandle,并更新函数内部的依赖项
  • 父组件修改state(类似异步),并且调用子组建init(类似同步),这个时候是来不及更新init中的依赖的,调用时使用了旧值;所以同步调用子组建init会拿到实时值,但是很有可能你希望获取最新值,一种解决方式是在init参数传入最新值,一种解决方式是子组建监听值的变化,调用对应的函数
  • 控制子组建init会避开数据流,导致在数据流变化之前就触发函数,需要注意init函数和最新的数据流的关系
  • 注意子组建中 await delay(0),然后setCount(count + 1);点击两次发现打印001122…,
    第一次点击:打印函数体内count = 0, delay(0) => (deps变化) => 更新函数体内count = 0(此时setCount还没有值更新)=>count = 1(实际值count);
    第二次点击:打印函数体内count = 0,delay(0)=> (deps变化) => 更新函数体内count = 1(实际值count)=>count = 1(实际值count);
    第三次点击:才会打印count为1
import { Col, message, Row, Space } from "antd";
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from "react";
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export function ChildRefTemp(props, ref) {const inputRef = useRef(null);const [count, setCount] = useState(0);const [age, setAge] = useState(0);const handleClick = () => {inputRef.current.focus();};const countAdd = async () => {// await delay(0);// 当设置延迟,props.count先让createHandle更新,这个时候count还没有更新,还是旧值展示;// 除了第一次点击,其他时候点击两次才可以让count + 1setCount(count + 1);};// useImperativeHandle: (ref, createHandle, deps)useImperativeHandle(ref,() => {console.log("ChildRefTemp useImperativeHandle"); // 初始化也会调用一次return {init(initCount) {inputRef.current.focus();countAdd();message.success("init" + count);message.success("init props.countRef: " + props.countRef);message.success("init initCount: " + initCount);}};},// 这里的deps依赖,会导致重新调用 createHandle;如果没有依赖,获取值的时候得不到最新值// [age] 不会导致重新调用 createHandle 生成新的handle// 父组件只设置props.countRef,不去setCount,不会导致子组建接收到最新的props.countRef;// 父组件setCount,子组件接收到最新的props.count,导致子组件并没有重新渲染,只要这里的值判断改变,createHandle 中就可以重新最新的数据[props.countRef]);return (<div><input type="text" ref={inputRef} /><button onClick={handleClick}>Focus Input</button><Row style={{ marginTop: 10 }}><Col><Space><span style={{ color: "red" }}>ParentRefcount: {props.count}</span><span style={{ color: "red" }}>ParentRef countRef: {props.countRef}</span><span>count: {count}</span></Space></Col></Row></div>);
}
// forwardRef: (component, props) => ref => component(props, ref)
const ChildRef = forwardRef(ChildRefTemp);export default function ParentRef() {const childRef = useRef(null);const countRef = useRef(0);const [count, setCount] = useState(0);const [name, setName] = useState(0);// 每一次组建更新,都会生成新的函数,addFunc在其他hooks都deps中都会被识别成值产生变化const addFunc = () => {setCount(count + 1);countRef.current = countRef.current + 1;childRef.current.init();};// useCallback 中的 deps 变化,才会触发重新生成新的函数;// 没有触发deps更新,也可以调用,但是其中的依赖项使用之前的快照值(set队列函数会显示正常)const handleClick = useCallback(() => {setCount(count + 1); // 引发组件更新// setCount((count) => count + 1); // 消息队列countRef.current = countRef.current + 1; // 不会引发组件更新;值的对比childRef.current.init(countRef.current);// message.success("handleClick" + count);// deps 数值或者引用地址的变化,都会触发重新调用生成新的handle}, [countRef.current]);return (<div><p>Parent</p><button onClick={handleClick}>Focus Input</button><hr /><p>ChildRef</p>// handleClick 函数也拥有地址,会被deps捕获识别;useCallback可以缓存函数,即函数地址不会更改<ChildRef ref={childRef} count={count} countRef={countRef.current} name={name} handleClick={handleClick} /></div>);
}

相关文章:

useCallback和forwardRef的联合使用

文章目录 一、useCallback二、forwardRef 总结了useCallback、forwardRef中的deps&#xff0c;以及操作子组建时会遇到数据流不同步的问题 一、useCallback useCallback可以缓存函数&#xff0c;这样避免组建更新导致的函数重建&#xff1b;useCallback在函数更新以后会在deps中…...

C# .NET CORE 开发问题汇总

1. error MSB4803: .NET Core 版本的 MSBuild 不支持“ResolveComReference”。请使用 .NET Framework 版本的 MSBuild。 引用了一个COM组件, 使用donet 命令时,提示不支持, 可以先将项目设置为x86以构建, 将COM引用添加到核心项目中&#xff0c;构建它&#xff0c;在obj\x86\…...

【C语言】拆数字组成最大数

相信你是最棒哒&#xff01;&#xff01;&#xff01; 文章目录 题目描述 正确代码 法一注释版 简洁版 法二注释版 简洁版 题目描述 任意输入一个自然数&#xff0c;输出该自然数的各位数字组成的最大数。例如&#xff0c;输入 1593 &#xff0c;则输出为 9531 。 输入描述 …...

【Git系列】根据提交打印邮箱

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Nginx在处理客户端请求的并发性发面是否依赖Linux的多线程原理

Nginx在处理客户端请求的并发性发面是否依赖Linux的多线程原理 Nginx 在处理客户端请求的并发性方面&#xff0c;并不依赖于 Linux 的多线程原理。 Nginx 的并发处理主要基于 事件驱动模型 和 异步非阻塞 I/O&#xff0c;而不是传统的多线程或多进程模型。 Nginx 的并发处理模…...

Python生成对抗神经网络GAN预测股票及LSTMs、ARIMA对比分析ETF金融时间序列可视化

全文链接&#xff1a;https://tecdat.cn/?p38528 本文聚焦于利用生成对抗网络&#xff08;GANs&#xff09;进行金融时间序列的概率预测。介绍了一种新颖的基于经济学驱动的生成器损失函数&#xff0c;使 GANs 更适用于分类任务并置于监督学习环境中&#xff0c;能给出价格回…...

深入了解C++中const的用法

文章目录 一、C中的const如何理解&#xff1f;二、C中的const与C语言中的const有何区别&#xff1f;三、const与指针、引用的结合使用 一、C中的const如何理解&#xff1f; 在C中&#xff0c;const是一个关键字&#xff0c;用来表示常量性&#xff0c;意在告诉编译器某些变量或…...

【Linux金典面试题(上)】41道Linux金典面试问题+详细解答,包含基本操作、系统维护、网络配置、脚本编程等问题。

大家好&#xff0c;我是摇光~&#xff0c;用大白话讲解所有你难懂的知识点 之前写了一篇关于 python 的面试题&#xff0c;感觉大家都很需要&#xff0c;所以打算出一个面试专栏。 【数据分析岗】Python金典面试题 这个专栏主要针对面试大数据岗位、数据分析岗位、数据运维等…...

利用Python实现多元回归预测汽车价格

引言: AI技术的热门使得大家对机器学习有了更多的关注,作为与AI技术息息相关的一门课程,从头了解基础的机器学习算法就显得十分有必要,如:梯度下降,线性回归等。 正文: 本文将讲解线性回归中多元回回归的案例 机器学习大致可以分为监督学习,非监督学习、半监督学习还…...

抓包软件fiddler和wireshark使用手册

fiddler官方文档 Fiddler 抓包教程1 Fiddler 抓包教程2 wireshark抓包学习 2添加链接描述 ip 过滤 ip.src_host ip.dst_host ip.addr mac 过滤 eth.src eth.dst eth.addr 端口过滤 tcp.port tcp.srcport tcp.dstport 协议类型过滤 arp dhcp 规则组合 and or...

初识三大 Observer

文章目录 ResizeObserver、MutationObserver和IntersectionObserver用MutationObserver实现图片懒加载MutationObserver 兼容性问题IntersectionObserver 应用MutationObserver和IntersectionObserver的区别IntersectionObserver 实例示例一&#xff1a;图片懒加载示例二&#…...

Eclipse MAT(Memory Analyzer Tool) 使用手册

参考&#xff1a;JAVA内存泄露使用MAT(Memory Analyzer Tool)快速定位代码 Eclipse MAT 1.15.0提示JDK版本最低需要使用17版本的&#xff0c;如果不想安装可以下载ZIP包&#xff0c;或者使用较低版本的MAT。 为了避免下载的17版本JDK和本地环境干扰&#xff0c;可以直接在MAT配…...

TongWe7.0-东方通TongWeb控制台无法访问 排查

**问题描述&#xff1a;**无法访问TongWeb的控制台 逐项排查&#xff1a; 1、控制台访问地址是否正确&#xff1a;http://IP:9060/console #IP是服务器的实际IP地址 2、确认TongWeb进程是否存在&#xff0c;执行命令&#xff1a;ps -ef|grep tongweb 3、确认TongWeb服务启动…...

Ariba Procurement: Administration_Master data

采购主数据集成Procurement Master Data Integration 注意&#xff1a;并非所有元素都是必需的&#xff0c;数据元素的名称可能根据ERP的不同&#xff0c;有所不同。 Types of Master Data Accounting 在SAP Ariba中的各种会计元素字段中&#xff0c;填充有效值选择列表。建…...

爬虫学习案例4

爬取猪八戒网站数据&#xff1a;2024-12-12 使用xpath解析元素&#xff0c;安装依赖库 pip install lxml使用selenium步骤我的上篇博客有提到&#xff0c;这里就不重复了 selenium使用博客导航 # 安装pip install lxml,使用xpath from lxml import etree import time from s…...

Angular模块化应用构建详解

文章目录 前言一、理解Angular模块&#xff08;NgModule&#xff09;二、创建功能模块三、懒加载模块以提高性能四、共享模块五、库模块六、最佳实践与注意事项七、案例研究&#xff1a;重构电子商务平台结语 前言 Angular是一款由Google支持的、用于构建动态Web应用程序的前端…...

51c大模型~合集89

我自己的原文哦~ https://blog.51cto.com/whaosoft/12815167 #OpenAI很会营销 而号称超强AI营销的灵感岛实测成效如何&#xff1f; OpenAI 是懂营销的&#xff0c;连续 12 天发布&#xff0c;每天一个新花样&#xff0c;如今刚过一半&#xff0c;热度依旧不减。 毫无疑问&…...

【蓝桥杯备战】Day 1

1.基础题目 LCR 018.验证回文串 给定一个字符串 s &#xff0c;验证 s 是否是 回文串 &#xff0c;只考虑字母和数字字符&#xff0c;可以忽略字母的大小写。 本题中&#xff0c;将空字符串定义为有效的 回文串 。 示例 1: 输入: s "A man, a plan, a canal: Panama…...

FedAdam算法:供给方信用,数据质量;更新一致性

FedAdam算法:供给方信用,数据质量;更新一致性 FedAdam算法概述 FedAdam是一种联邦学习(Federated Learning)算法。联邦学习是一种机器学习技术,它允许在多个设备或数据中心(称为客户端)上训练模型,而无需将数据集中到一个中央服务器,从而保护数据隐私。FedAdam主要用于…...

内存卡格式化后的数据恢复全攻略

一、内存卡格式化简述 内存卡&#xff0c;作为现代电子设备中不可或缺的存储媒介&#xff0c;广泛应用于手机、相机、行车记录仪等各类设备中。然而&#xff0c;在使用过程中&#xff0c;我们可能会遇到内存卡需要格式化的情况。格式化是一种将内存卡上的所有数据和文件系统清…...

介绍交叉熵损失(Cross-Entropy Loss)以及交叉熵在对比学习中的应用:中英双语

中文版 本文解释 交叉熵损失&#xff08;Cross-Entropy Loss&#xff09;&#xff0c;并结合对比学习的应用说明它如何工作&#xff0c;以及如何让正样本对更近、负样本对更远。 什么是交叉熵损失&#xff1f; 交叉熵损失是机器学习中常用的一种损失函数&#xff0c;主要用于…...

RabbitMQ的几个概念

注&#xff1a;这篇文章会随时添加新的内容&#xff0c;就是将RabbtiMQ中的概念添加到这里。助力大家的学习 自动ACK和手动ACK的区别 自动ACK和手动ACK是消息队列中两种不同的消息确认机制&#xff0c;它们在消息处理的可靠性和灵活性方面存在显著差异。 自动ACK&#xff08…...

Ollama部署大模型并安装WebUi

Ollama用于在本地运行和部署大型语言模型(LLMs)的工具,可以非常方便的部署本地大模型 安装 Linux curl -fsSL https://ollama.com/install.sh | sh我是ubuntu系统安装,其他系统可以看项目的开源地址有写 GitHub - ollama/ollama: Get up and running with Llama 3, Mist…...

Debedium如何忽略Oracle的purge命令

报错 截至目前3.0版本&#xff0c;Debezium的Oracle Connector并不支持purge table这个指令。 所以&#xff0c;在使用Debezium解析Oracle变更的时候&#xff0c;如果在源端执行了类似 purge table "$BIN… 的语句&#xff0c;就会导致Debezium罢工&#xff0c;日志里显…...

PlantUML 语言

PlantUML 是一种开源工具&#xff0c;用于通过简单的文本描述生成 UML 图。它支持多种 UML 图类型&#xff0c;如类图、序列图、用例图、活动图、组件图、状态图等。PlantUML 语言非常简洁&#xff0c;采用类似编程语言的语法&#xff0c;允许用户使用文本定义模型&#xff0c;…...

linux的 .so和.ko文件分别是什么?主要区别是什么?

前言&#xff1a; .so和.ko文件的主要区别在于它们的应用层次和功能不同。‌ 应用层次 .so文件‌&#xff1a;这是用户层的动态链接库&#xff08;Shared Object&#xff09;&#xff0c;主要用于用户态的程序中。 它用于动态链接&#xff0c;多个程序可以共享同一个库文件&…...

XX服务器上的npm不知道咋突然坏了

收到同事的V&#xff0c;说是&#xff1a;182上的npm不知道咋突然坏了&#xff0c;查到这里了&#xff0c;不敢动了。 咱一定要抓重点&#xff1a;突然坏了。这里的突然肯定不是瞬间&#xff08;大概率是上次可用&#xff0c;这次不可用&#xff0c;中间间隔了多长时间&#x…...

数据结构(优先级队列 :Priority Queue)

前言&#xff1a; 在计算机科学中&#xff0c;队列是一种非常常见的数据结构&#xff0c;它遵循先进先出&#xff08;FIFO&#xff09;的原则&#xff0c;也就是说&#xff0c;先进入队列的元素会先被处理。然而&#xff0c;在许多实际应用中&#xff0c;我们不仅仅需要按顺序…...

nginx.conf 请求时间部分参数说明新手教程

下面来说下nginx.conf 的部分参数&#xff0c;配置如下&#xff1a; http {include mime.types;default_type application/octet-stream;client_max_body_size 1000M;#log_format main $remote_addr - $remote_user [$time_local] "$request" # …...

【Linux-ubuntu通过USB传输程序点亮LED灯】

Linux-ubuntu通过USB传输程序点亮LED灯 一,初始化GPIO配置1.使能时钟2.其他寄存器配置 二&#xff0c;程序编译三&#xff0c;USB传输程序 一,初始化GPIO配置 1.使能时钟 使能就是一个控制信号&#xff0c;用于决定时钟信号是否能够有效的传递或者被使用&#xff0c;就像一个…...

用ps做网站方法/百度销售平台

2019独角兽企业重金招聘Python工程师标准>>> 概述 很多时候 mysql安装完root用户的默认密码不为空&#xff0c;这时候就需要通过其它办法登入到mysql重置密码。 步骤 方法1&#xff1a;查看/root/.mysql_secret文件 安装mysql第一次会生成一个随机密码&#xff0c…...

网站如何做地面推广/百度人工客服24小时

300道计算机应用基础试题简化版(附答案)第 PAGE 16 页 共 NUMPAGES 16 页计算机应用基础试题及答案(注&#xff1a; 200道选择&#xff0c;100道填空)一、选择题&#xff1a;1. 在计算机应用中&#xff0c;“计算机辅助设计”的英文缩写为___________。A. CAD 2. 微型计算机中&…...

微3g网站/关键词排名网络推广

[ 用大白话讲解复杂的技术 ]这是我的第41篇原创文章作者 l 会点代码的大叔(CodeDaShu)今天&#xff0c;我们来聊聊 Java 的注解。01注解的概念Annotation(注解)&#xff1a;先看看官方给出的概念&#xff0c;注解是 Java 提供的一种对元程序中元素关联信息和元数据的途径和方法…...

分布式加载网站的静态/郑州网络推广效果

一个理想的弹簧振子固定于墙上&#xff0c;来回振动&#xff0c;从室内人看&#xff0c;其机械能守恒, 从一匀速运动火车上看, 弹簧固定点在移动&#xff0c;而且固定点有作用力&#xff0c;因此外力对弹簧振子系统做功不为零, 弹簧的机械能不守恒.类似的另一情景...

和文化有关的吉网站建设模板/海南百度竞价推广

文章目录1. 《ClickHouse和Doris之OLAP谁与争锋》课程介绍1.1. 本次系列课程介绍1.2. 今日课程大纲2. ClickHouse 表引擎详解和架构原理2.1. ClickHouse 设计思想和核心技术特征2.1.1. ClickHouse 全知全解2.1.2. ClickHouse 设计思路剖析2.2. ClickHouse 表引擎详解2.2.1. Cli…...

wordpress微信付款插件/文员短期电脑培训

detail订单详情表字段名 数据类型 默认值 允许非空 自动递增 备注id int(11) NO 是 idorderid int(11) NO 订单id号goodsid int(11) NO 商品id号name varchar(32) NO 商品名称prince double(6,2) NO 单价num int(11) NO 数量orders订单表字段名 数据类型 默认值 允许非空 自动递…...