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.mzph.cn/news/139120.shtml

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

相关文章

SVN 服务器建立

1.建立SVN库 svnadmin create cat svndir/conf/passwd 修改SVN用户密码 chenht 123456 2.建立目录权限 [aliases] # joe /CXZ/STDessert/LSnake City/OSnake Oil, Ltd./OUResearch Institute/CNJoe Average [groups] # harry_and_sally harry,sally # harry_sally_…

嵌入式养成计划-52----ARM--开发板介绍--相关硬件基础内容介绍--GPIO讲解

一百三十一、开发板介绍 131.1 核心板介绍 131.2 拓展板 一百三十二、相关硬件基础内容介绍 132.1 PCB PCB&#xff08; Printed Circuit Board&#xff09;&#xff0c;中文名称为印制电路板&#xff0c;又称印刷线路板&#xff0c; 是重要的电子部件&#xff0c;是电子元器…

Linux常用命令——bzless命令

在线Linux命令查询工具 bzless 增强.bz2压缩包查看器 补充说明 bzless命令是增强“.bz2”压缩包查看器&#xff0c;bzless比bzmore命令功能更加强大。 语法 bzless(参数)参数 文件&#xff1a;指定要分屏显示的.bz2压缩包。 在线Linux命令查询工具

计算机毕业设计 基于Springboot的影院购票管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

Spring源码阅读-ClassPathXmlApplicationContext

第一步&#xff1a;new一个ClassPathXmlApplicationContext对象 ClassPathXmlApplicationContext xmlContext new ClassPathXmlApplicationContext("mylearn.xml"); 第二步&#xff1a;调用构造方法 public ClassPathXmlApplicationContext(String configLocatio…

网络运维Day10

文章目录 SHELL基础查看有哪些解释器使用usermod修改用户解释器BASH基本特性 shell脚本的设计与运行编写问世脚本脚本格式规范执行shell脚本方法一方法二实验 变量自定义变量环境变量位置变量案例 预定义变量 变量的扩展运用多种引号的区别双引号的应用单引号的应用反撇号或$()…

【海德教育】国家开放大学和函授区别有:学校不同、入学门槛不同、学习方式不同、招生对象不同、学习年限不同,具体如下:

一、学校不同。 国家开放大学的招收学校是中央电大和各省市、自治州、市辖区及单设的国家开放大学。函授是成人高考学习方式&#xff0c;成考是普通高等院校举行的、单设的成人高等学校。 二、入学门槛不同。 国家开放大学对入学者的年龄、职业、地区和学习资历等方面都没有太多…

力扣第72题 编辑距离 (增 删 改) C++ 动态规划 附Java代码

题目 72. 编辑距离 中等 相关标签 字符串 动态规划 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作&#xff1a; 插入一个字符删除一个字符替换一个字符 示例 1&#xff1a; 输入&a…

Python Fastapi+Vue+JWT实现注册、登录、状态续签【登录保持】

文章目录 一、实现流程1.注册2.登录3.登录保持【状态续签】二、实现方法1.注册2.登录+登陆状态保持* 后端部分* 前端部分一、实现流程 1.注册 Created with Raphal 2.3.0

【机器学习范式】监督学习,无监督学习,强化学习, 半监督学习,自监督学习,迁移学习,对比分析+详解与示例代码

目录 1. 监督学习 (Supervised Learning): 2. 无监督学习 (Unsupervised Learning): 3. 强化学习 (Reinforcement Learning): 4. 半监督学习 (Semi-Supervised Learning): 5. 自监督学习 (Self-Supervised Learning): 6. 迁移学习 (Transfer Learning): 7 机器学习范式应…

Git可视化界面的操作,SSH协议的以及IDEA集成Git

目录 一. Git可视化界面的操作 二. gitee的ssh key 2.1 SSH协议 2.2 ssh key 三. IDEA集成Git 3.1 分享项目 3.2 下载项目 一. Git可视化界面的操作 上一篇博客只用到了git的命令窗口&#xff0c;现在就来看看可视化窗口要怎么操作。 点击Git GUI Here GUI界面 在g…

ceph-deploy bclinux aarch64 ceph 14.2.10

ssh-copy-id&#xff0c;部署机免密登录其他三台主机 所有机器硬盘配置参考如下&#xff0c;计划采用vdb作为ceph数据盘 下载ceph-deploy pip install ceph-deploy 免密登录设置主机名 hostnamectl --static set-hostname ceph-0 .. 3 配置hosts 172.17.163.105 ceph-0 172.…

HTML使用lable将文字与控件进行关联以获取焦点

先养养眼再往下看 注释很详细&#xff0c;直接上代码 <form action""><!-- 第一种方法:用id的方式绑定账户(文字)和输入框 --><label for"zhanghu">账户</label><input "text" id"zhanghu" name"ac…

Python环境安装、Pycharm开发工具安装(IDE)

Python下载 Python官网 Python安装 Python安装成功 Pycharm集成开发工具下载&#xff08;IDE&#xff09; PC集成开发工具 Pycharm集成开发工具安装&#xff08;IDE&#xff09; 安装完成 添加环境变量&#xff08;前面勾选了Path不用配置&#xff09; &#xff08;1&…

NO.304 二维区域和检索 - 矩阵不可变

题目 给定一个二维矩阵 matrix&#xff0c;以下类型的多个请求&#xff1a; 计算其子矩形范围内元素的总和&#xff0c;该子矩阵的 左上角 为 (row1, col1) &#xff0c;右下角 为 (row2, col2) 。 实现 NumMatrix 类&#xff1a; NumMatrix(int[][] matrix) 给定整数矩阵 …

Redis数据库的使用

【官网】https://redis.com/ 【中文官网】https://redis.p2hp.com/ 【官方推荐的客户端】https://redis.io/resources/clients/ 1、Qt连接Redis的方式 第三方库c&#xff1a;【hiredis】https://github.com/redis/hiredis第三方库c&#xff1a;【redis-plus-plus】https://gi…

JS实现数据结构与算法

队列 1、普通队列 利用数组push和shif 就可以简单实现 2、利用链表的方式实现队列 class MyQueue {constructor(){this.head nullthis.tail nullthis.length 0}add(value){let node {value}if(this.length 0){this.head nodethis.tail node}else{this.tail.next no…

LLM代码生成器的挑战【GDELT早期观察】

越来越多的研究开始对LLM大模型生成的代码的质量提出质疑&#xff0c;尽管科技行业不断推出越来越多的旨在增强甚至取代人类编码员的工具。 随着我们&#xff08;GDELT&#xff09;继续探索和评估越来越多的此类工具&#xff0c;以下是我们的一些早期观察结果。 在线工具推荐&a…

【ARM Coresight OpenOCD 系列 3 -- OpenOCD 常用命令与扫描链scan_chain】

文章目录 1.1 TAP Declaration1.1.1 扫描链 1.2 Autoprobing1.3 DAP declaration (ARMv6-M, ARMv7 and ARMv8 targets) 1.1 TAP Declaration 测试访问端口&#xff08;TAP&#xff09;是JTAG的核心。TAP扮演许多角色&#xff0c;包括&#xff1a; 调试目标&#xff1a;CPU TA…

linux安装git

目录 声明 前言 正文 &#xff08;1&#xff09;下载git压缩包 &#xff08;2&#xff09;git压缩包解压 &#xff08;3&#xff09;解压完成后需要进行源码的编译操作 a.首先进去到解压后的文件目录中&#xff1a; b.执行&#xff1a; 编译的过程中可能遇到的问题&am…