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

React的useEvent 和 ahooks 的 useMemorizedFn 的深度分析和对比

父组件

const TestParent: React.FC<any> = () => {const [State, setState] = useState(0);const changeFun = useCallback(() => {console.log('useCallback closure 里的  State', State);}, [State]);const changeFun_useEvent = useEvent(() => {console.log('useEvent closure 里的  State', State);});const changeFun_usememrized = useMemorizedFn(() => {console.log('useMemorizedFn closure 里的  State', State);});return (<div style={{ width: '100%', padding: '20px', backgroundColor: 'green' }}>父组件的state: {State}<button onClick={() => setState(Math.random())}>click-change state</button><TestChild changeFun={changeFun_useEvent}></TestChild><TestChild changeFun={changeFun_usememrized}></TestChild></div>);
};

子组件

const TestChild = (props: any) => {const { changeFun } = props;useEffect(() => {console.log('changeFun-》地址change了,导致了子组件刷新了。');}, [changeFun]);return (<div style={{ backgroundColor: 'pink' }}>子组件<br /><br /><button onClick={changeFun}>child click - get parent's state </button></div>);
};
React.memo(TestChild);

useEvent

已被官方废弃

useEvent 源码解析

【解释1】
1、由于每次父组件更新,都会执行到 下面的代码。这个是首要条件!
const changeFun_useEvent = useEvent(() => {
console.log('useEvent closure 里的  State', State);
});

2、其次,每次执行都会传递过来一个新的handler,自然带来了新的闭包、新的数据。

3、最后,useLayoutEffect的作用是每次数据发生更新,自动的去执行里面的方法。

4、 所以 handlerRef.current 就能拿到带着最新数据的一个handler

【解释2】

useCallback 并且依赖为[],只执行一次,地址也就永远不会变了。
那么,useEvent()return出去函数的地址永不变化。

可以解释为

1、useEvent() return 出去了一个对象,为  obj = {A:{}}2、 useCallback里的箭头函数return出去的是这个 fn=handlerRef.current;相当于一个属性 A 由于handlerRef.current指向地址是不停变化的,所以A得指向地址就是不停变化的。3、因此我们真正使用 changeFun_useEvent=useEvent(xx)的时候, 拿到的是obj。永远不变的地址。changeFun_useEvent()调用的时候拿到的就是obj.A了。就是最新的带着最新数据的一个handler
function useEvent(handler: any) {const handlerRef = useRef(null);// In a real implementation, this would run before layout effects// 这行保证handlerRef一直处于,最新的闭包、拿到最新的数据。【解释1】useLayoutEffect(() => {console.log('useLayoutEffect执行了');handlerRef.current = handler;});
//这行保证返回的数据地址永远不变,但是执行的时候拿到的最新的。【解释2】return useCallback((...args: any) => {// In a real implementation, this would throw if called during renderconst fn = handlerRef.current;return fn(...args);}, []);
}
useMemorizedFn源码解析

源码地址
【解释1】
fn在这里做依赖的原因: 由于每次父组件重新执行,都会走到useMemorizedFn里并传过来一个新的箭头函数。所以fn每次地址都是新的。也就带来了新数据的闭包。fnRef.current也就是解释2里的A的地址每次都是新的,带着新的数据的闭包。

【解释2】
这里可以解释为: const obj = {A:{}} ;
memoizedFn.current = obj;
fnRef.current = A
当执行memoizedFn.current的时候也就是去访问并执行了 obj.A

function useMemorizedFn(fn: any) {const fnRef = useRef(fn);// 这行保证fn一直处于,最新的闭包、拿到最新的数据。【解释1】//这里为什么不直接  fnRef.current =  fn  ,可参考官网。总结就是 fnRef.current的需要放到useMemo。否则reactdev tool监听不到变化。fnRef.current = useMemo(() => {console.log('useMemo执行了'); // 父级改变就执行return fn;}, [fn]);const memoizedFn = useRef<any>();// 下面保证fn引用地址不变、且每次都能拿到最新的闭包 【解释2】if (!memoizedFn.current) {memoizedFn.current = function (this: any, ...args: any) {return fnRef.current.apply(this, args);//立即执行、改变this指向、传递参数 3个作用};}return memoizedFn.current;
}
总结

由此我们看出。其实二者的原理和出发点都是一致的,都是返回的是个固定的对象obj,该对象地址不变,但是调用的方法的时候相当于调用了obj.A,此属性的指向是会一直更新的。
只不过更新的时候 :useevent用了useLayoutCallback做更新,useMemorizedFn则使用了useMemo。
保持地址不变的时候:useevent用的是useCallback ,useMemorizedFn使用的一个 !memoizedFn.current + 新固定的function 。

此文纯属个人理解,有偏差望指正。

相关文章:

React的useEvent 和 ahooks 的 useMemorizedFn 的深度分析和对比

父组件 const TestParent: React.FC<any> () > {const [State, setState] useState(0);const changeFun useCallback(() > {console.log(useCallback closure 里的 State, State);}, [State]);const changeFun_useEvent useEvent(() > {console.log(useEv…...

基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统

goframe-admin goframe-admin V1.0.0 平台简介 基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统。前端采用tdesign-vue-next-starter 、vue3、pinia、tdesign-vue-next。 特征 高生产率&#xff1a;几分钟即可搭建一个后台管理系统认证机制&#x…...

LInux之在同一Tomcat下使用不同的端口号访问不同的项目

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《LInux实战开发》。&#x1f3af;&#x1f3af; …...

梦百合上榜2023鼎革奖数字化转型先锋榜

10月26日,第六届“鼎革奖”数字化转型先锋榜单揭晓,梦百合家居凭借数字化生产的卓越成果——SAP管理平台及供应链项目,入选2023【鼎革奖】数字化转型先锋榜年度供应链转型典范,梦百合家居COO 崔慧明同步入选2023【鼎革奖】数字化转型先锋榜年度首席运营官。 据了解,「鼎革奖」数…...

沉痛悼念科研分公司

今天上班途中&#xff0c;遇到了上家公司的同事王强。他正准备去体检中心体检。几句寒暄之后&#xff0c;得知他是要入职选煤公司了。 我们所在的公司比较大&#xff0c;总公司下设有几十个分、子公司&#xff0c;我和他曾经在一家子公司——科研分公司。现在的科研分公司解散…...

Django的网站项目开发好了,该用何种方案在Centos上部署【答:Gunicorn(uWSGI)+Nginx】

问&#xff1a;用Django开发的网站开发好了&#xff0c;现在要部署上线。 系统为Centos 7.x 现在我安装好Django和相关依赖后&#xff0c;我用命令 python manage.py runserver 127.0.0.1:8010 启动Django 然后安装配置好Nginx,并把用的请求转发到 127.0.0.1:8010 。 请问这样的…...

基于PyTorch的中文情绪分析器设计与开发

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、相关基础理论2.1 主流深度学习框架2.2 神经网络2.2.1 神经网络基础 二、中文情感分类模型构建3.1 开发环境3.2 数据部分3.3 文本特征提取3.3.1、过滤标点符号3.3.2 中文分词、单词过滤 三 运行结果与分析五 结…...

HT5010 音频转换器工作原理

HT5010是一款低成B的立体声DA转换器&#xff0c;内部集成了内插滤波器、DA转换器和输出模拟滤波等电路。其可支持多种音频数字输入格式&#xff0c;支持24-bit字节。 该HT5010 基于一个多比特位的Δ-Σ调制器&#xff0c;将数字信号转化成两个声道的模拟信号并经过模拟滤波器滤…...

ubuntu18.04如何更新到22.04

将linux系统中的Ubuntu 18.04更新到22.04&#xff0c;按照以下步骤操作&#xff1a; 打开终端并更新系统&#xff0c;使用以下命令&#xff1a; sudo apt update sudo apt upgrade sudo apt dist-upgrade 确保系统是最新的&#xff0c;然后备份数据&#xff0c;以防万一。执…...

嵌入式软件开发:第二部分–七个步骤计划

使用一种工具&#xff08;仅一种工具&#xff09;武装自己&#xff0c;您可以在下一个嵌入式项目的质量和交付时间上做出巨大的改进。点击领取嵌入式物联网学习路线 该工具是&#xff1a;绝对承诺对开发代码的方式进行一些小而基本的更改 。 有了改变的意志&#xff0c;今天您…...

什么是IPA,和RPA有啥区别和联系?

∵ IPA中包含了RPA的“PA”&#xff0c;AI的“I” ∴IPARPAAI&#xff0c;等式成立&#xff01; AI&#xff1a;或人工智能&#xff0c;是一种复杂的计算机技术&#xff0c;旨在模仿人类智能行为和决策的能力。它涵盖了多种技术和方法&#xff0c;包括&#xff1a;机器学习&am…...

内涝积水监测仪怎么样?万宾科技城市内涝积水监测的作用

在城市建设发展过程中&#xff0c;道路基础设施的建设永远都占据着重要一席&#xff0c;因为人们出行一旦受阻便会影响城市进展&#xff0c;也会影响经济发展。在城市之中有隧道&#xff0c;下穿式立交桥等容易存积水的地方&#xff0c;一旦出现恶劣暴雨天气&#xff0c;这些地…...

【java】命令行,包

文件夹情况&#xff1a; HelloWorld.java package com.demo; public class HelloWorld{public static void print(){System.out.println("HelloWorld!");}public static void main(String[] args){print();} } import.java import com.demo.HelloWorld; public cla…...

Generative AI 新世界 | 文生图(Text-to-Image)领域论文解读

在上期文章&#xff0c;我们开始探讨生成式 AI&#xff08;Generative AI&#xff09;的另一个进步迅速的领域&#xff1a;文生图&#xff08;Text-to-Image&#xff09;领域。概述了 CLIP、OpenCLIP、扩散模型、DALL-E-2 模型、Stable Diffusion 模型等文生图&#xff08;Text…...

03.从简单的sql开始

从简单的sql开始 一、sql语句的种类二、oracle的工作原理三、oracle数据库常见基础命令 一、sql语句的种类 下面是SQL语句的分类、常用语句、使用方法&#xff1a; 分类语句使用方法解释数据查询SELECTSELECT column1, column2, … FROM table_name WHERE condition;用于从表…...

JS加密/解密之jsjiami在线js加密的效率问题

故事背景 ​ 经常有客户反馈&#xff0c;v7加密的效率比v6低&#xff0c;但是安全性更好。这里我给大家科普一下关于jsjiami的优化诀窍。 示例源代码 // 伪代码 while (1) {var name ‘张三’ }优化后 var _name 张三; while (1) {var name _name }优化原理 相信很多朋…...

解决【spring boot】Process finished with exit code 0的问题

文章目录 1. 复现错误2. 分析错误3. 解决问题 1. 复现错误 今天从https://start.spring.io下载配置好的spring boot项目&#xff1a; 启动后却报出如下错误&#xff1a; 即Process finished with exit code 0 2. 分析错误 Process finished with exit code 0翻译成中文进程已完…...

模电学习路径

交流通路实质 列出电路方程1&#xff0c;方程1对时刻t做微分 所得方程1‘ 即为 交流通路 方程1对时刻t做微分&#xff1a;两个不同时刻的方程1相减&#xff0c;并 令两时刻差为 无穷小 微分 改成 差 模电学习路径&#xff1a; 理论 《电路原理》清华大学 于歆杰 朱桂萍 陆文…...

【Linux】配置JDKTomcat开发环境及MySQL安装和后端项目部署

目录 一、jdk安装配置 1. 传入资源 2. 解压 3. 配置 二、Tomcat安装 1. 解压开启 2. 开放端口 三、MySQL安装 1. 解压安装 2. 登入配置 四、后端部署 1. 数据库 2. 导入.war包 3. 修改端口 4.开启访问 一、jdk安装配置 打开虚拟机 Centos 登入账号&#xff…...

Modelsim 使用教程(3)——Projects

目录 一、概述 二、设计文件及tb 2.1 设计文件 counter.v 2.2 仿真文件 tcounter.v 三、操作流程 3.1 Create a New Project&#xff08;创建一个新的工程&#xff09; 3.2 Add Objects to the Project&#xff08;把代码加入项目&#xff09; 3.3 Compile the …...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

学习一下用鸿蒙​​DevEco Studio HarmonyOS5实现百度地图

在鸿蒙&#xff08;HarmonyOS5&#xff09;中集成百度地图&#xff0c;可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API&#xff0c;可以构建跨设备的定位、导航和地图展示功能。 ​​1. 鸿蒙环境准备​​ ​​开发工具​​&#xff1a;下载安装 ​​De…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

OPENCV图形计算面积、弧长API讲解(1)

一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积&#xff0c;这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能&#xff0c;常用的API…...

SpringSecurity+vue通用权限系统

SpringSecurityvue通用权限系统 采用主流的技术栈实现&#xff0c;Mysql数据库&#xff0c;SpringBoot2Mybatis Plus后端&#xff0c;redis缓存&#xff0c;安全框架 SpringSecurity &#xff0c;Vue3.2Element Plus实现后台管理。基于JWT技术实现前后端分离。项目开发同时采 …...