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

概念

生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是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 +1this.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.hqwc.cn/news/174224.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python3】【力扣题】263. 丑数

【力扣题】题目描述&#xff1a; 此题&#xff1a;正整数n&#xff0c;能被2或3或5整除&#xff0c;且不断除以2或3或5最终的数是1。 【Python3】代码&#xff1a; 1、解题思路&#xff1a;递归。 知识点&#xff1a;递归&#xff1a;函数中调用函数自身&#xff08;必须有退…

Java实现身份证号校验,最后一位校验码校验

中国居民身份证号码编码规则 第一、二位表示省&#xff08;自治区、直辖市、特别行政区&#xff09;。 第三、四位表示市&#xff08;地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码&#xff09;。其中&#xff0c;01-20&#xff0c;51-70表示省直辖市&#xff1b;21-5…

ChatGPT只算L1阶段,谷歌提出AGI完整路线图

按照谷歌这个标准来看&#xff0c;大多数已有AI产品其实都分别进入了不同的AGI阶段&#xff0c;但只仅限于在技能水平上——要谈及通用性&#xff0c;目前只有ChatGPT等模型完全合格。 AGI应该如何发展、最终呈什么样子&#xff1f; 现在&#xff0c;业内第一个标准率先发布&a…

智能巡检软件哪个好?中小企业如何提升工作效率与质量?

在当今数字化、智能化的时代&#xff0c;智能巡检软件作为一种高效的工具&#xff0c;已经在各行各业得到了广泛的应用。它利用物联网、大数据、人工智能等技术&#xff0c;为巡检工作提供了全面的解决方案&#xff0c;帮助企业实现数据化、智能化管理&#xff0c;提高工作效率…

SPI协议详解

SPI协议详解 文章目录 SPI协议详解前言一、SPI是什么&#xff1f;二、通信原理SPI 通信的 4 种工作模式 总结 前言 好久没写这种协议了&#xff0c;最近正好需要用到&#xff0c;便详细的复习一下。 一、SPI是什么&#xff1f; SPI是串行外设接口&#xff08;Serial Periphe…

通过Workstation工具制作CentOS8虚拟机模板

通过Workstation工具制作CentOS8虚拟机模板 1. 需求说明2. 安装模板虚拟机3. 配置模板虚拟机 1. 需求说明 说明&#xff1a;在做集群实验过程中&#xff0c;需要创建多台虚拟机&#xff0c;如果逐台安装虚拟机&#xff0c;很消耗时间&#xff0c;所以最简洁的办法就是通过模板克…

数据结构 | 栈的实现

数据结构 | 栈的实现 文章目录 数据结构 | 栈的实现栈的概念及结构栈的实现 Stack.h初始化栈入栈出栈获取栈顶元素获取栈中有效元素个数检测栈是否为空销毁栈 Stack.c 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。…

【Python】【应用】Python应用之一行命令搭建http、ftp服务器

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;Python应用&…

Pytorch教程(代码逐行解释)

0、配准环境教程 1、开始导入相应的包 import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensortorch是pytorch的简写 torch.utils.data import DataLoader 是用于读取数…

数据结构:反射

基本概念 反射中的四个类 Class类 Java文件在被编译之后&#xff0c;生成了.class文件&#xff0c;JVM此时解读.class文件&#xff0c;将其解析为java.lang.Class 对象&#xff0c;在程序运行时每个java文件就最终变成了Class类对象的一个实例。通过反射机制应用这个 实例就…

C# 异步日志记录类,方便下次使用,不用重复造轮子

先定义接口类&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 异常 {internal interface ILog{Task WriteErrorLog(string message);Task WriteInfoLog(string message);Task W…

MySQL索引下推:提升数据库性能的关键优化技术

文章目录 前言索引下推原理MySQL 基础架构传统查询过程ICP 查询过程 使用场景限制参数配置索引下推开启状态查询索引下推开启和关闭 一些问题只有联合索引才能使用索引下推&#xff1f;下面的查询为什么不走索引下推 参考 前言 大家好&#xff0c;我是 Lorin &#xff0c;今天…