React中的useEffect(副作用)介绍

 更新时间:2024年01月04日 08:44:35   作者:前端小草籽  
这篇文章主要介绍了React中的useEffect(副作用),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

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.写法四:清除副作用写法

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

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

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Hello React的组件化方式之React入门小案例演示

    Hello React的组件化方式之React入门小案例演示

    这篇文章主要介绍了Hello React的组件化方式-React入门小案例,本文通过Hello React的案例, 来体验一下React开发模式, 以及jsx的语法,需要的朋友可以参考下
    2022-10-10
  • React + Typescript领域初学者的常见问题和技巧(最新)

    React + Typescript领域初学者的常见问题和技巧(最新)

    这篇文章主要介绍了React + Typescript领域初学者的常见问题和技巧,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 为react组件库添加typescript类型提示的方法

    为react组件库添加typescript类型提示的方法

    这篇文章主要介绍了为react组件库添加typescript类型提示,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • React中的受控组件与非受控组件详解

    React中的受控组件与非受控组件详解

    在React中,受控组件指的是表单元素的value值受React组件的state或props控制的组件,而非受控组件则是表单元素的value值由DOM自身负责管理的组件,本文将给大家详细介绍React受控组件与非受控组件,需要的朋友可以参考下
    2023-08-08
  • react-router-dom入门使用教程(前端路由原理)

    react-router-dom入门使用教程(前端路由原理)

    这篇文章主要介绍了react-router-dom入门使用教程,主要包括react路由相关理解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • react项目中@路径简单配置指南

    react项目中@路径简单配置指南

    这篇文章主要给大家介绍了关于react项目中@路径简单配置的相关资料,文中还介绍了React配置@路径别名的方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • React Fiber构建源码解析

    React Fiber构建源码解析

    这篇文章主要为大家介绍了React Fiber构建源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • React实现动态调用的弹框组件

    React实现动态调用的弹框组件

    这篇文章主要为大家详细介绍了React实现动态调用的弹框组件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • React函数组件hook原理及构建hook链表算法详情

    React函数组件hook原理及构建hook链表算法详情

    这篇文章主要介绍了React函数组件hook原理及构建hook链表算法详情,每一个 hook 函数都有对应的 hook 对象保存状态信息,更多详细分析,需要的朋友可以参考一下
    2022-07-07
  • React中异步数据更新不及时问题及解决

    React中异步数据更新不及时问题及解决

    这篇文章主要介绍了React中异步数据更新不及时问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03

最新评论