React中的useEffect(副作用)
创始人
2024-01-22 16:20:56
0

目录

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值这些。

 

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...