react类式组件的生命周期和useEffect实现函数组件生命周期

news2024/12/23 13:05:45

概念

生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的.

....
多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更容易理解,我在学习react的时候,也经常会想着这个api如果在vue里面会和哪个api功能相同.

其实有些本末倒置了,先有react才有的vue,vue是作者做了更多的操作,让你用到更舒适的api,还是那个经典形容,react是手动打,vue是自动挡.

废话不多说,开始说react的生命周期

...

如果想直接死记硬背八股文,直接拉到底看总结就可以了

类式组件

在hooks出来之前,写react基本都是用类式组件

两个原因,一是对this这个东西有特别的喜爱(vue后遗症),二是类式组件可以使用生命周期和state,适合开发业务组件.

测试各个钩子函数的demo
import React, { Component} from 'react'
export default class index extends Component {
 constructor(){
    super()
  console.log(this,'constructor---构造器')
 }

 state = {
    num:1
 }
 add = ()=>{
    let newNum = this.state.num +1
    this.setState({
        num:newNum
    })
 }
 


//生命周期钩子(旧的)
//  componentWillMount =()=>{
//     console.log('componentWillMount---组件将要加载')
//  }

//  componentWillUpdate = ()=>{
//     console.log('componentWillUpdate','组件将要更新')
//  }


//生命周期钩子(新的)
static getDerivedStateFromProps = ()=>{
    console.log(this,'getDerivedStateFromProps---初始化一些基础状态')
    return null
}

getSnapshotBeforeUpdate = ()=>{
    console.log(this,'getSnapshotBeforeUpdate---更新之前的快照')
    return '旧的值'
}





 //新旧都具备的

 shouldComponentUpdate = ()=>{
    console.log(this,'shouldComponentUpdate','组件需要更新')
    return true
 }
 componentDidUpdate = ()=>{
    console.log(this,'componentDidUpdate','组件更新完毕')
 }

 componentDidMount = ()=>{
    console.log(this,'componentDidMount---组件加载完成')
 }

 updateCallBack = ()=>{
  this.forceUpdate()
 }
  render() {
    console.log(this,'render---渲染函数')
    return (
      <div id='index'>
        <h3>生命周期模块</h3> 
        <button onClick={this.add}>修改一下数值</button>
        <p>{this.state.num}</p>
        <button onClick={this.updateCallBack}>手动更新</button>
        <br />
      </div>
    )
  }
   componentWillUnmount = ()=>{
    console.log(this,'componentWillUnmount---组件将要卸载')
 }
}

场景:

1.页面初次加载

constructor > getDerivedStateFromProps > render > componentDidMount

2.点击修改一下数值按钮

getDerivedStateFromProps > shouldComponentUpdate > render > getSnapshotBeforeUpdate >

componentDidUpdate

 3.手动更新(forceUpdate函数)

getDerivedStateFromProps > render > getSnapshotBeforeUpdate > componentDidUpdate

 4.卸载当前组件

componentWillUnmount

生命周期经典图

解读一下:

好吧,其实没有什么太多好解读的,本人的react内力没有那么深厚,这张图就是刚才我们实验的结果

初始化,自动更新,手动更新,卸载

你只要把这个demo自己写一下,就瞬间知道这个图是干啥的了,除了很长的单词比较难写,其余都好说.

你以为这样就完了吗,不不不,没有没有没有.这里还有两个需要专门说的

两个疑问
1.生命周期连续调用了两次的问题

造成这个原因是因为你的根组件使用了严格模式 React.StrictMode

ReactDOM.createRoot(document.getElementById('root')).render(
  <Provider store={store}>
    {/* <React.StrictMode> 把它注释掉就可以了*/}   
    <App />
    {/* </React.StrictMode> */}
    
  </Provider>
)
2.父子组件生命周期顺序(测试demo)

初始化

父costructor > 父 getDerviedStateFromProps > 父render >子costructor >子getDerviedStateFromProps > 子render > 子componentDidMount >父componentDidMount

 父组件修改值触发更新

父 getDerivedStateFromProps > 父 shouldComponentUpdate > 父 render > 子 getDrivedStateFromprops > 子shouldComponentUpdate > 子 render > 子 getSnaphotBeforeUpdate > 父getSnapshotBeforeUpdate > 子 componentDidUpdate> 父 componentDidUpdate

父组件手动更新

父 getDerivedStateFromProps > 父render > 子 getDerivedStateFromProps > 子 shouldComponentUpdate > 子render > 子getSnapshotBeforeUpdate > 父getSnapshotBeforeUpdate > 子componentDidUpdate > 父componentDidUpdate

 组件卸载

父componentWillUnmount > 子componentWillUnmount

函数组件

函数组件实现生命周期是需要借助一个api的,这个api叫做useEffect.

demo
import React,{useState,useEffect} from 'react'
import {Button} from 'antd'
export default function index(props) {
    const [num1,changeNum1] = useState(0)
    const [num2,changeNum2] = useState(10)
    //单个-----------------------------------------------------
    //首次加载,修改num1,修改num2,卸载当前组件没有
    useEffect(()=>{
        console.log('只传一个函数')
    })
    //首次加载,num1没有,num2没有,卸载当前组件没有
    useEffect(()=>{
        console.log('参数二传一个空数组')
    },[])
    //首次加载,修改num1,num2没有,卸载当前组件没有
    useEffect(()=>{
        console.log('传参数num1')
    },[num1])
    //首次加载,num1没有,修改num2,卸载当前组件没有
    useEffect(()=>{
        console.log('传参数num2')
    },[num2])
    //首次加载,修改num1,修改num2,卸载当前组件没有
    useEffect(()=>{
        console.log('都传')
    },[num1,num2])
    //首次没有,修改num1,修改num2,卸载组件调用
    useEffect(()=>{
        return ()=>{
            console.log('return方法')
        }
    })
    // 总结:
    // 1.参数1:函数:   初始化和每次修改参数都会触发这个函数
    // 2.参树2:空数组: 只有首次加载会触发
    // 3.参数2:某条数据: 首次加载和修改该数据都会触发
    // 4.参数2:多条数据: 首次加载和修改数组内任意一条数据都会触发
    // 5.参数1:函数返回一个函数: 首次不急在,但是修改任意数值和卸载组件时都会调用

  return (
    <div>
      <p>数值1:{num1}<Button onClick={()=>changeNum1(num1+1)}>修改数值1</Button></p>
      <p>数值2:{num2}<Button onClick={()=>changeNum2(num2-1)}>修改数值2</Button></p>
    </div>
  )
}

 初始化

 修改值1

组件卸载

实现初始化,更新,单独的数据更新,卸载
import React,{useState,useEffect} from 'react'
import {Button} from 'antd'
export default function index(props) {
    const [num1,changeNum1] = useState(0)
    const [num2,changeNum2] = useState(10)

    // 组合------------------------------------------------------
    
    // 场景1: 初始化加载
    useEffect(()=>{
        console.log('初始化加载')
        console.log(num1,'???',props)
    },[])

    //场景2: 任意数据更新,但是初始化不加载
    useEffect(()=>{
        return ()=>{
            console.log('数据发生修改了')
        }

    })
    //场景3: 只有卸载时加载
    useEffect(()=>{
        return ()=>{
            console.log('卸载才会调用')
        }

    },[])
    //场景4: 某一数据发生改变,单独触发
    useEffect(()=>{
        return ()=>{
            console.log('只有修改num1才会调用')
        }
    },[num1])

  return (
    <div>
      <p>数值1:{num1}<Button onClick={()=>changeNum1(num1+1)}>修改数值1</Button></p>
      <p>数值2:{num2}<Button onClick={()=>changeNum2(num2-1)}>修改数值2</Button></p>
    </div>
  )
}

总结

类式组件
各阶段钩子调用顺序
初始化constructor > getDerivedStateFromProps > render > componentDidMount
自动更新

getDerivedStateFromProps > shouldComponentUpdate > render > getSnapshotBeforeUpdate >

componentDidUpdate 

手动更新getDerivedStateFromProps > render > getSnapshotBeforeUpdate > componentDidUpdate
卸载componentWillUnmount
父子组件生命周期
初始化父costructor > 父 getDerviedStateFromProps > 父render >子costructor >子getDerviedStateFromProps > 子render > 子componentDidMount >父componentDidMount
父组件自动更新父 getDerivedStateFromProps > 父 shouldComponentUpdate > 父 render > 子 getDrivedStateFromprops > 子shouldComponentUpdate > 子 render > 子 getSnaphotBeforeUpdate > 父getSnapshotBeforeUpdate > 子 componentDidUpdate> 父 componentDidUpdate
父组件手动更新父 getDerivedStateFromProps > 父render > 子 getDerivedStateFromProps > 子 shouldComponentUpdate > 子render > 子getSnapshotBeforeUpdate > 父getSnapshotBeforeUpdate > 子componentDidUpdate > 父componentDidUpdate
卸载父componentWillUnmount > 子componentWillUnmount
钩子函数连续调用两次的问题解决

干掉根组件的 React.StrictMode

函数组件
只在初始化加载调用

    useEffect(()=>{

        console.log('初始化加载')

    },[])

初始化不调用但是更新组件会调用

    useEffect(()=>{

        return ()=>{

            console.log('数据发生修改了')

        }

    })

单独的数据发生变化进行调用

    useEffect(()=>{

        return ()=>{

            console.log('只有修改num1才会调用')

        }

    },[num1])

只在组件卸载时调用

    useEffect(()=>{

        return ()=>{

            console.log('卸载才会调用')

        }

    },[])

尾声

我的这篇博客没有专门讲这些api在调用时都发生了啥,主要是让读者了解react生命周期的api调用时机,属于业务开发中实用知识点,感觉还行的看客老爷们给个赞吧!

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

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

相关文章

echarts饼图label显示不全原因?

echarts饼图label显示不全原因&#xff1f; 标签数量过多&#xff1a;当饼图的扇形数量较多时&#xff0c;为了保证图形的清晰性&#xff0c;ECharts 可能不会显示所有的标签&#xff0c;而是选择显示部分标签或者不显示标签。标签过长&#xff1a;如果标签的文字过长&#xf…

软件测试常用的测试方法详解

软件测试是软件开发过程中重要组成部分&#xff0c;是用来确认一个程序的质量或者性能是否符合开发之前提出的一些要求。软件测试的目的有两方面&#xff0c;一方面是确认软件的质量&#xff0c;另一方面是提供信息&#xff0c;例如&#xff0c;给开发人员或者程序经理反馈意见…

基于springboot实现家具商城管理系统项目【项目源码】计算机毕业设计

基于springboot实现家具商城管理系统演示 Java语言简介 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备了显著的…

vue+nodejs商城实战项目【登录 + 购物车 + 支付】

从零开始一个前端项目并将其完成需要经历一系列步骤。以下是一个常见的开发流程&#xff0c;可以帮助规划和管理项目&#xff1a; 需求分析和规划&#xff1a; 确定项目的目标和范围。定义用户需求和功能要求。制定项目计划和时间表。 技术选型&#xff1a; 选择适当的前端技术…

Jira Software Enterprise Crack

Jira Software Enterprise Crack Jira软件是为您的应用程序组中的每一个成员设计、监控和启动优秀软件的。 策略&#xff1a;生成用户故事和问题&#xff0c;策略冲刺&#xff0c;并在应用程序团队中分配任务。 跟踪&#xff1a;在具有绝对可见性的完整背景下&#xff0c;确定团…

【论文阅读笔记】Detecting AI Trojans Using Meta Neural Analysis

个人阅读笔记&#xff0c;如有错误欢迎指出&#xff01; 会议&#xff1a;2021 S&P Detecting AI Trojans Using Meta Neural Analysis | IEEE Conference Publication | IEEE Xplore 问题&#xff1a; 当前防御方法存在一些难以实现的假设&#xff0c;或者要求直…

基本数据类型小题两道

根据公式计算A地区教师任教年薪&#xff0c;统计键盘输入的字符串中数字个数&#xff0c;按字典序输出。 (笔记模板由python脚本于2023年11月10日 18:05:18创建&#xff0c;本篇笔记适合熟悉python列表、元、字符串等基本数据类型的coder翻阅) 【学习的细节是欢悦的历程】 Pyth…

vue同时校验多个表单

0 效果 1 代码 checkForm (formRef) {return new Promise((resolve, reject) > {this.$refs[formRef].validate((valid) > {if (valid) {resolve();} else {setTimeout(() > {this.$refs[formRef].clearValidate();reject(new Error(错误));}, 1500);}});}); }, conf…

【unity3D】Input Field组件(可供用户输入的文本框)

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的Input Field组件 Input Field组件 基础属性详细解释 Unity中的InputField组件可以用来创建一个可供用户输入的文本框。 基础属性…

Linux内核密码模块

目录 密码算法介绍 Hash摘要算法 Cipher加解密算法 块密码算法 认证算法 MAC和HMAC AEAD算法 Linux内核密码模块的基本构件 Linux内核密码模块介绍 如何使用Linux密码模块 用户层调用Linux内核密码模块的方法 cryptodev AF_ALG 如何开发一个密码引擎驱动 开发一个…

Pycharm常用快捷键和替换正则表达式

原生快捷键的使用&#xff1a; 1.CtrlF&#xff1a;查找 2.CtrlZ&#xff1a;返回上一步 3.Alt 鼠标左键选择&#xff1a;多行同时编辑&#xff08;上、下、左、右键能够移动光标&#xff09; 按住Ctrl,左键点击&#xff0c;定位光标 编辑过程 URL常用的替换正则表达式&am…

从小白到测试专家:掌握Pytest的实用技巧和优秀实践

pytest是一个功能丰富且易于使用的Python测试框架&#xff0c;它建立在Python标准库的unittest模块之上&#xff0c;提供了更简洁、灵活和可读性强的测试代码编写方式。下面&#xff0c;我将按照步骤引导您学习pytest。 步骤1&#xff1a;安装pytest 首先&#xff0c;您需要安装…

python3.8及以上版本绑定gdal库的一个注意事项

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> gdal和python绑定参考文章&#xff1a;windows环境下python和gdal绑定方法   值得注意的是绑定python3.8及以上版本后在python程序中初始化gdal库时会出…

自媒体项目详述

总体框架 本项目主要着手于获取最新最热新闻资讯&#xff0c;以微服务构架为技术基础搭建校内仅供学生教师使用的校园新媒体app。以文章为主线的核心业务主要分为如下子模块。自媒体模块实现用户创建功能、文章发布功能、素材管理功能。app端用户模块实现文章搜索、文章点赞、…

Qt QTableWidget表格的宽度

默认值 QTableWIdget的表格宽度默认是一个给定值&#xff0c;可以手动调整每列的宽度&#xff0c;也不填满父窗口 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {this->resize(800,600);QStringList contents{"11","111111111111",&…

ios 对话框 弹框,输入对话框 普通对话框

1 普通对话框 UIAlertController* alert [UIAlertController alertControllerWithTitle:"a" message:"alert12222fdsfs" pr…

Springboot自动装配(SPI技术、@Import动态加载配置类)

SpringBoot原理 起步依赖 依赖传递&#xff0c;a依赖b&#xff0c;b依赖c 自动配置 Springboot的自动配置就是当Spring容器启动后&#xff0c;一些配置类、bean对象就自动存入到了IOC容器中&#xff0c;不用手动配置了 Springboot采用的是EnableXXXX注解&#xff0c;分装…

带你一分钟看懂 “Docker”

2010年&#xff0c;几个搞IT的年轻人&#xff0c;在美国旧金山成立了一家名叫“dotCloud”的公司。 这家公司主要提供基于PaaS的云计算技术服务。具体来说&#xff0c;是和LXC有关的容器技术。 后来&#xff0c;dotCloud公司将自己的容器技术进行了简化和标准化&#xff0c;并…

腾讯云优惠券是什么?详细介绍及领取攻略来了!

1、腾讯云优惠券介绍 腾讯云优惠券是腾讯云推出的一种优惠活动&#xff0c;包括代金券和折扣券。代金券是可抵扣费用的优惠券&#xff0c;可以在结算时使用代金券抵扣订单金额。折扣券可以在结算时使用享受一定的折扣优惠。 2、腾讯云优惠券领取 领取入口&#xff1a;txy.in…

Bond配置文件配置

1、选择2个自己需要的网口&#xff0c;查看有哪些网口 [roothostname ~]# ifconfig -a [roothostname ~]#systemctl disable NetworkManager 开机不启动图形化网络服务 2、编辑网口的配置文件 [roothostname ~]# cd /etc/sysconfig/network-scripts [roothostname n…