React中的useEffect(副作用)

news2025/7/9 3:23:45

目录

useEffect(副作用)介绍

useEffect(副作用)各种写法的调用时刻

1.写法一:没有依赖项时

父组件给子组件传值:

 2.写法二:依赖项中有监听的值时

 3.写法三:依赖项为空数组时

4.写法4:清除副作用写法(假如副作用是一个定时器,清除定时器,如果不清的话,会出现内存泄漏)

5.写法五:依赖项是一个函数的时候

注意点


useEffect(副作用)介绍

useEffect是用来使函数组件也可以进行副作用操作的。那么什么是副作用呢?

函数的副作用就是函数除了返回值外对外界环境造成的其它影响。举个例子,假如我们每次执行一个函数,该函数都会操作全局的一个变量,那么对全局变量的操作就是这个函数的副作用。而在React的世界里,我们的副作用大体可以分为两类,一类是调用浏览器的API,例如使用addEventListener来添加事件监听函数等,另外一类是发起获取服务器数据的请求,例如当用户组件挂载的时候去异步获取用户的信息等。

react官方的原话:

如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。

componentDidMount 组件挂载
componentDidUpdate 组件更新
componentWillUnmount 组件将要摧毁

语法:

import {useEffect} from "react"
useEffect(() => {
  /** 执行逻辑 */
  }, dependencies)  //dependencies是一个数组,是可选的

//或者:
useEffect(effect?=>clean?, dependencies?)

 useEffect的第一个参数 effect 是要执行的副作用函数,它可以是任意的用户自定义函数,用户可以在这个函数里面操作一些浏览器的API或者和外部环境进行交互,网络请求等,这个函数会在每次组件渲染完成之后被调用。useEffect可以有一个返回值,返回一个函数,系统在组件重新渲染之前调用,用于清除副作用(比如说副作用是定时器,return里面就可以写清除定时器的代码)。它第二个参数dependencies(依赖项)来限制该副作用的执行条件  

useEffect(副作用)各种写法的调用时刻

1.写法一:没有依赖项时

useEffect所在组件每次渲染(包括首次)时都要调用:组件中任何变化都会执行(eg:useState解构出的state改了就会引发组件重新渲染,父组件给子组件传递属性的值改变,子组件中的useEffect就会执行)

  //没有依赖项
  useEffect(()=>{
    console.log('组件每次渲染时都要调用(页面每次刷新)');
  })

组件生命周期里面有一种生命周期父组件给子组件传新的属性就会调用的生命周期函数,useEffect写法一就可以替代。

组件自身状态变化会调用beforeupdateupdated,useEffect写法一就可以替代。

父组件给子组件传值:

 2.写法二:依赖项中有监听的值时

根据依赖项中监听的变量是否变化决定是否执行副作用,变了就执行,不变就不执行

    //依赖项中有值时
    //页面首次渲染和父组件给子组件传的属性值和子组件自身的值改变(依赖项改变才会打印)
    useEffect(() => {
        console.log('页面首次渲染和依赖项改变的时候才会打印');
    },[num,props.title])

 3.写法三:依赖项为空数组时

相当于Vue生命周期函数mounted,也就是页面首次渲染(挂载)后,后面不管组件中值咋改变都不会执行了,除非该组件销毁了再重新挂载时才会执行。

    useEffect(() => {
        console.log('页面首次渲染');
    },[])

4.写法4:清除副作用写法(假如副作用是一个定时器,清除定时器,如果不清的话,会出现内存泄漏)

    useEffect(() => {
        let timer = setInterval(()=>{
            console.log(66666);
        },1000)
        return ()=>{
            //当组件下一次渲染前,执行这个函数:清除副作用(计时器就是一种副作用)
            console.log('当组件下一次渲染前,执行这个函数:清除副作用');
            clearInterval(timer);
        }
    })//这里没写依赖项,所以页面中的值改变就会刷新,比如useState解构出的state改变

 问题:副作用函数不会有缓存,那为什么在副作用函数useEffect里面写了定时器,页面(组件)刷新之后上一个定时器没有清除?就非要写return 返回一个函数去清除副作用(定时器)

5.写法五:依赖项是一个函数的时候

    let fn = ()=>{
        console.log(11111111);
    }
    useEffect(() => {
        console.log('此组件渲染时,就会运行(包括首次渲染)');
        // 该组件渲染时(包括首次渲染),就会执行副作用
        let timer = setInterval(()=>{
            console.log(66666);
        },1000)
        return ()=>{
            //而当该组件下一次运行(渲染)时,才会执行清除副作用函数(第一次渲染不执行(组件首次渲染时),下一次渲染才执行)
            console.log('当组件下一次渲染前,执行这个函数:清除副作用');
            clearInterval(timer);
        }
    },[fn])

 

 分析:当依赖项 fn 函数运行的时候,副作用函数才会运行(先执行副作用函数的return返回的函数,把上一次渲染生成的定时器清除,才会执行副作用函数,重新生成一个定时器),但是return返回的函数不一定运行,因为return返回的函数必须要是在该组件下一次渲染时,才会执行。因为fn函数虽然执行,但是并没有引起组件重新渲染,所以并不会执行return返回的函数。

缺点是:函数组件刷新时,函数fn又会重新生成一模一样的,没必要,会占用内存。有没有一种技术,在组件刷新时,这种像fn函数的,不重新生成,就用原来内存中的fn,就不用去重新开辟内存空间去生成函数fn。所以就用到了useCallback

注意点

1.

    //这种没依赖项
    let [data,setData] = useState('');
    useEffect(()=>{
        //这里可以进行请求后台数据,但是不能通过setData()将请求回来的数据把页面刷新
        //会陷入死循环,页面一刷新 useEffect就会执行,就会请求后台数据,请求回来的数据又
        //通过setData()导致页面数据改变然后刷新,这样就会陷入死循环
        setData();
    })   

    //如果有依赖项的话,就不会陷入死循环

2.组件重新渲染时,会将那些非hook相关的数据重新生成一份,比如说,

    let [num,setNum] = useState(100);  //hook相关的数据
    let m = 100;            //普通的数据
    let arr = [100,200,900];//普通的引用数据
    let fm = ()=>{}         //普通的引用数据

 

 

以use开头的那些hook组件刷新时不会重新生成,那些普通的数据会重新生成。如果依赖项是这种普通的arr,fm等引用数据,组件刷新时,就会重新生成,重新开辟内存空间生成,所以就会导致副作用函数执行,所以一般副作用函数的依赖项都是父组件给子组件传的属性或者useState解构出的state值这些。

 

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

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

相关文章

【C++】string类的模拟实现

文章目录一、string类的构造、拷贝构造、赋值重载以及析构1.构造函数2.拷贝构造3.swap问题4.赋值重载5.析构函数二、常用接口1.c_str2.[]3.迭代器和范围for4.size和capacity三、插入1.reserve和resize2.push_back3.append4.5.insert四、删除1.erase2.clear五、查找1.find六、运…

Nginx

What is Nginx? Nginx 同 Apache 一样都是一种 Web 服务器。基于 REST 架构风格,以统一资源描述符(Uniform Resources Identifier)URI 或者统一资源定位符(Uniform Resources Locator)URL 作为沟通依据&…

基于51单片机的多功能时钟温度计proteus仿真原理图

本系统是由AT89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压环境中工作;时钟电路由内部时钟电路外接晶振提供,它是一种高性能、低功耗、带RAM的可随时调整时钟电路,工作电压为3V~…

数据中台与大数据、数据仓库、数据湖、BI的区别

一、什么是数据中台 数据中台是一种将企业沉睡的数据变成数据资产,持续使用数据、产生智能、为业务服务,从而实现数据价值变现的系统和机制。通过数据中台提供的方法和运行机制,形成汇聚整合、提纯加工、建模处理、算法学习,并以…

电源管理ISL95869HRTZ、ISL95808HRZ概述、规格和应用

ISL95869完全符合英特尔IMVP9规范,并为处理器的主输入轨道电源提供了完整的解决方案。它提供了一个电压调节器(VR)与两个集成和一个外部门驱动器。VR可以配置为3-,2-或1-相位,提供最大的灵活性。虚拟现实采用串行控制总线SVID (serial contro…

es环境搭建

1.es与es-head的搭建 1.1 es7.6.2 每个es都是自成一个集群,不同于solar还需要zk来搭建集群 1.1.1 下载安装 https://www.elastic.co/cn/downloads/past-releases/elasticsearch-7-6-2 因为占用内存实在是太大了,我在服务器上装了运行不起来&#xff…

Flameshot源码编译方法

一、简介 Flameshot是一款功能强大但易于使用的屏幕截图软件,中文名称火焰截图。Flameshot 简单易用并有一个CLI版本,所以你也可以从命令行来进行截图。Flameshot 是一个Linux发行版中完全免费且开源的截图工具。 二、在线安装 在线安装方法很简单&…

java基于web的自行车租赁系统ssh

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1 课题背景 1 1.2 课题研究的意义 1 1.3 课题的目标 2 1.4 研究内容与章节安排 2 第2章 可行性分析 3 2.1 经济可行性 3 2.2 技术可行性 3 2.3 操作可行性 4 2.4法律可行性 4 2.5业务流程分析…

win10实现nfs文件共享II

文章目录(一)在服务器A设置共享目录(二)在客户端B安装nfs,挂载目录(一)在服务器A设置共享目录 步骤1:在D盘新建目录“nfs”,将其目录设置为共享目录。 步骤2:点击权限,设…

税票贷产品的准入与额度判断有哪些逻辑

近两周,番茄风控的课程中,涉及的税票贷产品课程干货满满。 今天我们再跟大家讲一下关于税票贷中风控的核心准入策略与额度判断有哪些逻辑是需要关注的? 先来说下税务的数据,然后再来讲下发票类型的数据。 一.关于税务的风控准入策…

PCB Layout爬电距离、电气间隙如何确定-安规

PCB Layout爬电距离、电气间隙如何确定 爬电距离:沿绝缘表面测得的两个导电零部件之间或导电零部件与设备防护界面之间的最短路径。 电气间隙:在两个导电零部件之间或导电零部件与设备防护界面之间测得的最短空间距离。即在保证电气性能稳定和安全的情况…

Redis真没那么难,这份大佬实战笔记也太可了,吹爆

Redis的技术全景 Redis一个开源的基于键值对(Key-Value)NoSQL数据库。使用ANSI C语言编写、支持网络、基于内存但支持持久化。性能优秀,并提供多种语言的API。 我们要首先理解一点,我们把Redis称为KV数据库,键值对数据…

图解LeetCode——775. 全局倒置与局部倒置(难度:中等)

一、题目 给你一个长度为 n 的整数数组 nums &#xff0c;表示由范围 [0, n - 1] 内所有整数组成的一个排列。 全局倒置 的数目等于满足下述条件不同下标对 (i, j) 的数目&#xff1a; 0 < i < j < nnums[i] > nums[j]局部倒置 的数目等于满足下述条件的下标 i 的…

【Opencv实战】识别水果的软件叫什么?一款超好用的识别软件分享,一秒鉴定(真是活~久~见~啊)

导语 Hello&#xff0c;大家好呀&#xff01;我是木木子吖&#xff5e; 一个集美貌幽默风趣善良可爱并努力码代码的程序媛一枚。 听说关注我的人会一夜暴富发大财哦——不信你试试&#xff01; 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝白嫖源码福利&…

redis(二)

一、短信登录 1.1导入黑马点评项目 导入黑马点评项目 首先&#xff0c;导入课前资料提供的SQL文件 其中的表有&#xff1a; tb_user&#xff1a;用户表tb_user_info&#xff1a;用户详情表tb_shop&#xff1a;商户信息表tb_shop_type&#xff1a;商户类型表tb_blog&#xf…

Golang入门(1)—— helloworld 初体验

没有多少雄心壮志&#xff0c;就是想在B站上跟一个视频&#xff0c;写一个helloworld 。 还是老配方&#xff0c;还是IDEA&#xff0c;简单的下载了一个go插件之后&#xff0c;就可以new go文件了。然后根据提示下载了一个最新的go版本&#xff0c;设置好环境变量。写了如下&am…

Redis事务相关源码探究

文章目录Redis事务源码解读1、MULTI 声明事务2、命令入队3、EXEC 执行事务4、WATCH 监听变量Redis事务源码解读 源码地址&#xff1a;https://github.com/redis/redis/tree/7.0/src 从源码来简单分析下 Redis 中事务的实现过程 1、MULTI 声明事务 Redis 中使用 MULTI 命令来…

Ubuntu18.04 安装完成后的开发配置

Ubuntu18.04 安装完成后的开发配置1 终端工具2 屏幕录制工具3 屏幕截图工具4 向日葵远程操作与开机自启动设置5 MarkDown笔记工具6 ROS 机器人操作系统安装7 编程开发工具8 机器人仿真环境Gazebo 安装Webots 安装CoppeliaSim 安装Mujuco 安装Pybullet 安装测试平台&#xff1a;…

【c#】前后端分离练习小项目学习笔记----纯干货

c#实现前端页面CRUD结果图涉及到的技术设计流程代码展示总结结果图 涉及到的技术 1、HttpClient请求网络 2、webapi接口用法 3、sqlsugar数据库使用 4、Json序列化、反序列化 设计流程 刚开始做这个小项目&#xff0c;很懵。按照平常中项目的写法&#xff0c;就是先配置好数据…

模式识别与机器学习(更新中)

模式识别与机器学习 使用的教材&#xff0c;PPT为1 公式推导部分直接去看白板推导2&#xff0c;不管是书上还是ppt都写的极其模糊 先说重点&#xff1a; 贝叶斯算概率参数估计 第二讲 贝叶斯学习基础 贝叶斯公式 先验概率是非条件概率 似然概率是给定变量的条件下观测变…