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

总结

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

相关文章

  • React鼠标多选功能的配置方法

    React鼠标多选功能的配置方法

    本文给大家分享React鼠标多选功能,通过导入组件直接包裹已经设计好的列表即可,操作简单方便,对React鼠标多选相关知识感兴趣的朋友一起看看吧
    2021-05-05
  • React 首页加载慢问题性能优化案例详解

    React 首页加载慢问题性能优化案例详解

    这篇文章主要介绍了React 首页加载慢问题性能优化案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • React实现锚点跳转组件附带吸顶效果的示例代码

    React实现锚点跳转组件附带吸顶效果的示例代码

    这篇文章主要为大家详细介绍了React如何实现移动端锚点跳转组件附带吸顶效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-01-01
  • 详解React中如何拆分组件

    详解React中如何拆分组件

    这篇文章主要为大家详细介绍了React中拆分组件的相关知识,文中的示例代码讲解详细,对我们掌握React有一定的帮助,需要的小伙伴可以参考一下
    2023-12-12
  • React中refs的一些常见用法汇总

    React中refs的一些常见用法汇总

    Refs是一个 获取 DOM节点或React元素实例的工具,在React中Refs 提供了一种方式,允许用户访问DOM 节点或者在render方法中创建的React元素,这篇文章主要给大家介绍了关于React中refs的一些常见用法,需要的朋友可以参考下
    2021-07-07
  • ReactJs快速入门教程(精华版)

    ReactJs快速入门教程(精华版)

    React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站.这篇文章主要介绍了ReactJs快速入门教程(精华版)的相关资料,需要的朋友可以参考下
    2016-11-11
  • 一文学会使用Remix写API接口

    一文学会使用Remix写API接口

    这篇文章主要为大家介绍了一文学会Remix写API接口实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • React工作流程及Error Boundaries实现过程讲解

    React工作流程及Error Boundaries实现过程讲解

    这篇文章主要介绍了React工作流程及Error Boundaries实现过程讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-02-02
  • webpack3+React 的配置全解

    webpack3+React 的配置全解

    本篇文章主要介绍了webpack3+React 的配置全解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • react+antd动态增删表单方式

    react+antd动态增删表单方式

    这篇文章主要介绍了react+antd动态增删表单方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论