useEffect,useLayoutEffect的基础知识和底层机制

news2024/11/25 20:11:55

useEffect 是 React 中一个重要的 Hook,用来处理组件的副作用操作。它的基础知识包括两个方面:执行时机和参数。

执行时机:

useEff ect 的执行时机包括两种情况:

  1. 组件挂载时,即第一次渲染之后。
  2. 组件更新时,即组件的 props 或状态发生变化时。

参数:

useEffect 接收两个参数:一个函数和一个依赖数组。

  1. 函数:这个函数会在组件的挂载和更新时被调用,它可以包含一些副作用操作,比如修改 DOM、发送网络请求等等。
  2. 依赖数组:这个数组是一个可选参数,用来指定 useEffect 的依赖项。如果一个组件中需要多次调用 useEffect,那么每次调用都需要指定依赖数组。当依赖数组中的任何一个值发生变化时,才会触发 useEffect 的重新执行。如果依赖数组为空,则表示 useEffect 没有任何依赖,只会在组件挂载和卸载时执行。

写法

  1. useEffect(callback):font color=red>这个参数表示只要组件发生更新,就会执行回调函数 callback,包括组件挂载时的初始化和后续状态或属性的更新。如果不需要依赖任何状态或属性,相当于类组件中的 componentDidMountcomponentDidUpdate 的合并。
  2. useEffect(callback, []):这个参数表示只在组件挂载时执行一次回调函数 callback,不会在组件更新时执行。这个参数当中传入的空数组 [] 表示没有任何依赖,因此只有在组件挂载时才会执行。
  3. useEffect(callback, [state1, state2, ...]) 这个参数表示在组件挂载时执行一次回调函数 callback,之后只有 state1state2 等指定的依赖状态发生改变时才会执行回调函数。如果多个状态都需要依赖,可以在数组中传入多个状态名称。
   useEffect( ()=>{
       return ()=>{
      //返回的小函数,会在组件释放的时候执行
      //如果组件更新,会把上一次函数执行,返回的小函数执行
       console.[log( '@4' ,num );
    });

需要注意的是,如果在 callback 中进行了一些异步操作,比如发起网络请求,需要在组件被销毁时主动取消这些异步操作,以防止内存泄漏。可以使用 useEffect 返回的清除函数来实现这个功能。例如:

useEffect(() => {
  const fetchData = async () => {
    // 发起异步请求
  }
  fetchData();

  return () => {
    // 取消异步请求
  }
}, [state1])

在这个例子中,fetchData 函数是一个异步操作,会在组件挂载和 state1 发生改变时被调用。在 useEffect 的回调函数中返回了一个清除函数,该函数会在组件被销毁时调用,用来取消异步请求操作。

底层机制:

基于effect链表实行!!!是异步的,effect 链表是指在一个 useEffect 钩子中,可以有多个副作用函数(或称为 effect 函数)。这些副作用函数会被按照它们声明的顺序依次执行,形成一条链表。当组件更新时,这些函数也会被按照它们声明的顺序依次执行。

在这里插入图片描述


useLayoutEffect和useEffect的细节

1.需求:在num大于5的时候我们再ueseffect

if ( num > 5){
useEffect( ( ) => {
lconsole.log ( 'OK');
});
}

会报错useEffect必须在函数的最外层上下文中调用,不能把其嵌入到条件判断、循环等操作语句中,应该这样做

useEffect(() => {
  if (num > 5) {
    console.log('OK');
  }
}, [num]);

2.模拟从服务器异步获取数据

错误写法:

在这里插入图片描述

在这个例子中,这里返回的是一个promise实例,而不是一个函数,我们试图在 useEffect 中使用 async/await,然后在函数体内调用 queryData 函数获取数据并打印到控制台上。但是你需要注意,useEffect 钩子中的副作用函数必须是同步的函数(或者返回一个清除函数的函数),而 async/await 函数是异步的函数,因此不能直接在 useEffect 中使用。

可以将副作用函数的主体逻辑封装到一个单独的函数中,然后在 useEffect 中调用这个函数:

const fetchData = async () => {
  let data = await queryData();
  console.log('成功: ', data);
};

useEffect(() => {
  fetchData();
  return () => {
        // 在组件卸载前,清除副作用
        console.log('清除 fetchData 副作用');
    };
}, []);

在这个例子中,我们将获取数据并打印到控制台的操作封装到了 fetchData 函数中,这个函数是一个异步的 async 函数。然后我们在 useEffect 中调用了这个 fetchData 函数。由于 useEffect 存在异步特性,因此不会阻塞其它的组件渲染,而副作用 fetchData 会在组件初次渲染时被调用,并且不会被重复执行(因为依赖列表是空的)。

需要注意的是,我们不能直接将 fetchData 函数放在 useEffect 中调用,而是需要先将它定义成一个变量。因为在 useEffect 中定义的函数会被作为闭包存储,并且它们的引用关系不会随着组件更新而改变。如果我们直接在 useEffect 中定义 async/await 函数,那么这个函数的引用关系会在每个组件更新时被重置,从而无法实现我们的预期效果。

3.什么是副作用函数??

根据上一个问题,fetchData 函数中包含了异步操作,比如网络请求,这些异步操作具有副作用。因此 fetchData 函数被视为具有副作用的函数。

在函数式编程语言中,副作用是指函数对外部环境造成的影响,这些影响可能会改变系统状态或返回一些不可预测的结果。在 JavaScript 中,一些常见的副作用包括修改全局状态、改变 DOM、读写本地存储、发出网络请求等等。

由于副作用的不确定性和可变性,React 为我们提供了钩子函数,例如 useEffect,以及一些限制和规范,来管理和控制副作用。在 React 中,我们应该尽量避免直接操作 DOM,而应该通过钩子函数和状态管理来更新视图和响应用户操作。


useLayoutEffect

1.useLayoutEffectuseEffect 很相似,都是 React 提供的用于处理副作用的钩子函数。它们的主要区别在于执行时间不同。
在这里插入图片描述

useLayoutEffect在第二步结束的时候渲染,useEffect在第三步结束的时候渲染

2.useEffect 会在浏览器完成绘制后,即组件渲染到页面上后异步执行。也就是说,可能会在用户看到更新前看到旧的 UI。而 useLayoutEffect 会在浏览器绘制之前同步执行,useLayoutEffect会阻止浏览器渲染真实DOM,优先执行Effect链表中的callback;
这里的渲染是指绘制
,useLayoutEffect 执行时,组件返回的 JSX 已经被渲染成 DOM,但 DOM 还没有完成 layout,也就是还没有完成测量和定位。相对于 useEffect,useLayoutEffect 触发的时机更早,可以拿到更快更准确的测量值,同时又避免了闪烁和触发重渲染的问题。因此可以在 useLayoutEffect 中进行对真实 DOM 的操作。,确保无论是 React 还是 DOM 视图都是最新的,即用户看到的 UI 是最新的。

如果你需要在更新 DOM 前同步更新某些组件或页面状态并且必须优先更新,可以使用 useLayoutEffect。如果不需要优先更新或状态更新较慢也不会影响用户体验,可以使用 useEffect

需要注意,由于 useLayoutEffect 的同步执行,如果钩子函数的操作逻辑较耗时,则可能会导致页面卡顿或延迟加载。因此,应该谨慎使用 useLayoutEffect,避免出现性能问题。

渲染次数问题:

如果在callback函数中又修改了状态值「视图又要更新」
1.useEffect:浏览器肯定是把第一次的真实已经绘制了,再去渲染第二次真实DOM
2.useLayoutEffect:浏览器是把两次真实DOM的渲染,合并在一起渲染的

总结

1. 视图更新的步骤

  • 将 JSX 编译为 createElement 格式并调用,创建出 Virtual DOM。
  • 基于 root.render 方法将 Virtual DOM 转换为真实 DOM 对象。
  • 执行更新队列中已记录的所有组件的生命周期方法,包括 shouldComponentUpdaterendergetSnapshotBeforeUpdatecomponentDidUpdate 等方法。
  • 基于 Virtual DOM 树比较上一次渲染时的 virtual DOM 树和本次渲染时的 virtual DOM 树,找出两棵树之间的差异,并记录需要更新的 DOM 对象的最小集合。
  • 在浏览器空闲时间内执行更新和重绘操作,优化更新过的 DOM 对象,尽可能减少页面的重排和重绘的次数,提高页面的性能和响应速度。

2. useLayoutEffect 和 useEffect 的区别

  • useLayoutEffect 与 useEffect 在实现上是类似的,不同之处在于 useLayoutEffect 的回调函数会在 DOM 更新之后,浏览器执行绘制之前被调用,而 useEffect 的回调函数则是在浏览器执行绘制之后被调用。
  • useLayoutEffect 在执行回调函数时会产生阻塞效果,可能会导致页面感觉卡顿,而 useEffect 则不会产生这种阻塞效果。
  • 因此,如果回调函数需要操作 DOM 或者进行某些与界面交互相关的操作,可以考虑使用 useLayoutEffect;如果不需要进行交互,或者交互操作可以忍受一定的延迟,可以使用 useEffect。

3. 视图更新如何影响性能和用户体验

  • 视图更新是一种相对费时的操作,如果更新操作过于频繁或过于复杂,可能会影响页面的性能和响应速度,甚至引起页面卡顿等问题。
  • 对于频繁进行更新的组件,可以考虑使用 React.memouseMemouseCallback 等优化方式,避免重复的计算和更新。
  • 对于需要操作 DOM 或进行其他交互操作的组件,要特别注意使用 useLayoutEffectuseEffect 时的延迟问题和阻塞效果,避免影响页面的流畅度和响应速度。同时,也要考虑好性能和用户体验之间的平衡,避免过度追求优化而影响用户的体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/647413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能垃圾分类小程序,流量主变现,外卖cps权益变现,uniCloud云开发无需购买服务器和域名,助力每一位创业者。

技术优势 基于 uniapp uniCloud 研发,无需购买服务器和域名,uniCloud 是 DCloud 联合阿里云、腾讯云 serverless 构建。从此不用关心服务器运维、弹性扩容、大并发承载、防DDoS攻击等,轻松应对高并发应用, 传统小程序开通流量主…

Qt 多语言实现

简介 Qt Linguist 提供了一套加速应用程序翻译和国际化的工具。Qt 使用单一的源码树和单一的应用程序二进制包就可同时支持多个语言和书写系统。 使用 QTranslator 来加载生成的 qm 文件,就可以让程序显示指定的语言。 // 国际化翻译 QString language "CH…

项目Es、kafka、mysql容量评估方案和服务器资源预估方案

目录 1、Es 评估计划 一个接口jmeter压测qps 1万, logstash 读取日志文件写入es Logstash配置 Es容量变化前后差值/1万 * 1.67 * (1副本数) ~ 次接口es 容量 (日志数据30kb) 影响es存储的主要原因 通过 kibana 查看 堆栈》索…

管理类联考——英语——技巧篇——阅读理解

一、阅读理解A节选项的点 1.正确答案的五大特征 (1)“主题为王”原则:即正确答案通常与文章的中心思想、主旨大意有关。 (2)正确答案的特点:语言简化、反话正说、正话反说、关键词替换。 (3)正确答案要选相对的,不选绝对的。正确答案通常含有…

编译原理期末速成-LL(1)文法、FIRST集、FOLLOW集

文章目录 LL(1)文法的条件LL(1)分析法构造FIRST(α)构造FOLLOW(A)习题强化 LL(1)文法的条件 文法不含左递归 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。即若 对于文法中的每个非终结符A,若它存在某个候选首符集包含ε,则 这里&am…

面试被问到:测试计划和测试方案有什么区别?

面试的时候,很多小伙伴都被面试官问过这个问题 “测试计划和测试方案有什么区别”? 到底有什么区别呢?我们先好好了解下这两个文档。 一、测试计划 1、测试计划是什么? 测试计划是组织管理层面的文件,从组织管理的…

Jetpack Compose 中使用 CameraX 拍照和录制视频

在 Android 开发的历史中,Camera 的 API 是一直受人诟病的,使用过的人都知道,直观的感觉就是配置复杂、臃肿、难用、不易理解,从官方关于 Camera 的 API 迭代路线可以看出官方也在尝试着不断改进开发者关于Camera的使用体验&#…

ChatGPT编程

ChatGPT问答 问题一:如何合理分配时间问题二:以下是提高工作效率的建议:问题三:如何培养兴趣问题四:软件和硬件谁重要问题五: 设计模式如何熟练运用问题六:C语言编程冒泡排序 问题一:如何合理分配时间 这里…

Java实训第八天——2023.6.14

文章目录 一、vue的环境搭建:二、文本数据绑定三、属性数据绑定四、事件绑定五、案例1——全选/全不选六、案例2——切换图片主要内容: v-if 、v-show指令 七、表单数据绑定八、综合练习总结步骤: 一、vue的环境搭建: 官方文档&a…

Mysql数据库中的约束、用户管理与授权

文章目录 一、Mysql中常见的约束总结 二、数据表高级操作2.1克隆表,将数据表的数据记录生成到新的表中2.2清空表,删除表内的所有数据2.3创建临时表2.4创建外键约束,保证数据的完整性和一致性。 三、数据库用户管理3.1新建用户3.2查看用户信息…

《设计模式》之适配器模式

文章目录 1、定义2、动机3、应用场景4、类结构5、优缺点6、总结7、代码实现(C) 1、定义 把一个类的接口转换成客户端所期待的另一种接口,从而使原接口不匹配而无法再一起工作的两个类能在一起工作。 2、动机 在软件系统中,由于应用环境的变化&#xf…

Spring源码解密--事务篇

文章目录 一、事务的实现方式1、JDBC2、Spring基于xml配置编程式事务声明式事务 二、源码设计1、TransactionManager1)TransactionManager2)PlatformTransactionManager3)ReactiveTransactionManager 2、TransactionDefinition3、Transaction…

压缩感知入门——基于总体最小二乘的扰动压缩感知

压缩感知系列博客:压缩感知入门①从零开始压缩感知压缩感知入门②信号的稀疏表示和约束等距性压缩感知入门③基于ADMM的全变分正则化的压缩感知重构算法 文章目录 1. Problem2. 仿真结果3. MATLAB算法4. 源码地址参考文献 1. Problem 一个经典的压缩感知重构问题可以…

Git的原理与使用

背景知识: 我们在编写各种文档时,为了防止文档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出一个副本。每个版本有各自的内容,但最终会只有一份报告需要被我们使用 。但在此之前的工作都需要这些不…

day10_类中成员之变量

通过以前的学习,我们知道了成员变量是类的重要组成部分。对象的属性以变量形式存在,下面我们就来详解的学习一下类中的变量 成员变量 成员变量的分类 实例变量:没有static修饰,也叫对象属性,属于某个对象的&#xf…

9k字长文理解Transformer: Attention Is All You Need

作者:猛码Memmat 目录 Abstract1 Introduction2 Background3 Model Architecture3.1 Encoder and Decoder Stacks3.2 Attention3.2.1 Scaled Dot-Product Attention3.2.2 Multi-Head Attention3.2.3 Applications of Attention in our Model 3.3 Position-wise Feed…

Linux 数据库 MySQL

Linux系统分类 ^ 数据库的分类 Linux系统 Centos(获取软件包使用yum、dnf) Ubuntu(获取软件包使用apt-get) Suse 国产系统 华为 欧拉 阿里 龙蜥 腾讯 tencentOS 麒麟(银河麒麟、中标麒麟->基于centos 优麒麟-> 基于Ubuntu ) 统…

流计算、Flink和图计算

流计算 流计算流计算概述静态数据和流数据批量计算和实时计算流计算概念流计算与Hadoop流计算框架 流计算处理流程数据处理流程数据实时采集数据实时计算实时查询服务 流计算的应用开源流计算框架StormStorm简介Storm的特点 FlinkFlink简介为什么选择Flink传统数据处理架构大数…

三年 Android 开发的技术人生,浅谈自身面试的感悟

文章素材来源于网友 本篇主要记录了一个 Android 菜瓜三年的面试之旅,希望对大家面试、跳槽有所帮助。 一些唠叨 从进入这行开始,就是听说Android端凉了,寒冬这又如何那又如何的事情,很多的风言风语缠绕着这个圈子。但是老弟觉得…

电商系统架构设计系列(三):关于「订单系统」有哪些问题是要特别考虑的?

订单系统是整个电商系统中最重要的一个子系统,订单数据也就是电商企业最重要的数据资产。 上篇文章中,我给你留了一个思考题:当系统在创建和更新订单时,如何保证数据准确无误呢? 今天这篇文章,主要聊一下&…