React 生命周期完整指南
React 生命周期完整指南
1. 生命周期概述
1.1 React 16.3 之前的生命周期
- 初始化阶段
- constructor
- componentWillMount
- render
- componentDidMount
- 更新阶段
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
- 卸载阶段
- componentWillUnmount
1.2 React 16.3 之后的生命周期
- 初始化阶段
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
- 更新阶段
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
- 卸载阶段
- componentWillUnmount
2. 详细说明
2.1 挂载阶段
class MyComponent extends React.Component {// 1. 构造函数constructor(props) {super(props);this.state = {count: 0};console.log('1. constructor');}// 2. 派生状态static getDerivedStateFromProps(props, state) {console.log('2. getDerivedStateFromProps');return null;}// 3. 渲染render() {console.log('3. render');return <div>{this.state.count}</div>;}// 4. 挂载完成componentDidMount() {console.log('4. componentDidMount');}
}
2.2 更新阶段
class UpdateComponent extends React.Component {// 1. 派生状态static getDerivedStateFromProps(props, state) {console.log('1. getDerivedStateFromProps');return null;}// 2. 是否应该更新shouldComponentUpdate(nextProps, nextState) {console.log('2. shouldComponentUpdate');return true;}// 3. 渲染render() {console.log('3. render');return <div>{this.state.count}</div>;}// 4. 获取更新前的快照getSnapshotBeforeUpdate(prevProps, prevState) {console.log('4. getSnapshotBeforeUpdate');return null;}// 5. 更新完成componentDidUpdate(prevProps, prevState, snapshot) {console.log('5. componentDidUpdate');}
}
2.3 卸载阶段
class UnmountComponent extends React.Component {componentWillUnmount() {console.log('componentWillUnmount');// 清理工作:取消订阅、清除定时器等}
}
3. 新旧生命周期对比
3.1 被移除的生命周期方法
componentWillMount
// 旧版本
componentWillMount() {// 组件即将挂载// 问题:可能会导致服务器端渲染问题
}// 新版本替代方案
componentDidMount() {// 组件已挂载// 建议在这里进行异步操作
}
componentWillReceiveProps
// 旧版本
componentWillReceiveProps(nextProps) {// 即将接收新的 propsif (nextProps.value !== this.props.value) {this.setState({ value: nextProps.value });}
}// 新版本替代方案
static getDerivedStateFromProps(props, state) {if (props.value !== state.value) {return { value: props.value };}return null;
}
componentWillUpdate
// 旧版本
componentWillUpdate(nextProps, nextState) {// 即将更新// 问题:可能会导致异步渲染问题
}// 新版本替代方案
getSnapshotBeforeUpdate(prevProps, prevState) {// 获取更新前的快照return null;
}
3.2 新增的生命周期方法
getDerivedStateFromProps
class Example extends React.Component {static getDerivedStateFromProps(props, state) {// 返回新状态或 nullif (props.currentRow !== state.lastRow) {return {isScrollingDown: props.currentRow > state.lastRow,lastRow: props.currentRow};}return null;}
}
getSnapshotBeforeUpdate
class ScrollingList extends React.Component {getSnapshotBeforeUpdate(prevProps, prevState) {// 捕获更新前的信息if (prevProps.list.length < this.props.list.length) {const list = this.listRef.current;return list.scrollHeight - list.scrollTop;}return null;}componentDidUpdate(prevProps, prevState, snapshot) {// 使用快照信息if (snapshot !== null) {const list = this.listRef.current;list.scrollTop = list.scrollHeight - snapshot;}}
}
4. 生命周期最佳实践
4.1 常见用途
class BestPractices extends React.Component {constructor(props) {super(props);// 初始化状态// 绑定方法}static getDerivedStateFromProps(props, state) {// 用于状态的派生// 不要在这里执行副作用return null;}componentDidMount() {// 适合执行副作用// - 网络请求// - DOM 操作// - 订阅}shouldComponentUpdate(nextProps, nextState) {// 性能优化// 返回 false 可以阻止更新return true;}getSnapshotBeforeUpdate(prevProps, prevState) {// 获取 DOM 更新前的信息return null;}componentDidUpdate(prevProps, prevState, snapshot) {// 更新后的操作// 可以执行副作用// 注意避免无限循环}componentWillUnmount() {// 清理工作// - 取消订阅// - 清除定时器// - 取消网络请求}
}
4.2 错误处理
class ErrorBoundary extends React.Component {state = { hasError: false };static getDerivedStateFromError(error) {// 更新状态,下次渲染时显示降级 UIreturn { hasError: true };}componentDidCatch(error, errorInfo) {// 记录错误信息console.error('Error:', error);console.error('Error Info:', errorInfo);}render() {if (this.state.hasError) {return <h1>Something went wrong.</h1>;}return this.props.children;}
}
5. Hooks 时代的生命周期
5.1 使用 Hooks 模拟生命周期
function HooksLifecycle() {// 模拟 constructorconst [state, setState] = useState({count: 0});// 模拟 componentDidMountuseEffect(() => {console.log('Component mounted');return () => {// 模拟 componentWillUnmountconsole.log('Component will unmount');};}, []);// 模拟 componentDidUpdateuseEffect(() => {console.log('State updated:', state);}, [state]);return <div>{state.count}</div>;
}
5.2 生命周期方法与 Hooks 对照表
生命周期方法 | Hooks 实现 |
---|---|
constructor | useState |
componentDidMount | useEffect(() => {}, []) |
componentDidUpdate | useEffect(() => {}, [deps]) |
componentWillUnmount | useEffect(() => { return () => {} }, []) |
shouldComponentUpdate | useMemo, useCallback |
getDerivedStateFromProps | useState + useEffect |
6. 总结
6.1 生命周期选择建议
- 使用
componentDidMount
进行初始化操作 - 使用
componentDidUpdate
响应更新 - 使用
componentWillUnmount
清理资源 - 优先考虑新的生命周期方法
- 在合适的场景使用 Hooks
6.2 注意事项
- 避免在构造函数中执行副作用
- 不要在
getDerivedStateFromProps
中执行副作用 - 谨慎使用
shouldComponentUpdate
- 在
componentDidUpdate
中注意避免无限循环 - 确保在
componentWillUnmount
中清理所有副作用
6.3函数组件中的生命周期(通过 Hooks)
useEffect 可以模拟 componentDidMount 和 componentDidUpdate,通过将依赖项传递给 useEffect 来控制副作用的执行。传递空数组 [] 作为依赖项时,useEffect 只会在组件首次挂载时执行,相当于 componentDidMount。
清理副作用:useEffect 可以返回一个清理函数,相当于类组件中的 componentWillUnmount。
import React, { useState, useEffect } from 'react';const MyFunctionComponent = () => {const [counter, setCounter] = useState(0);// 模拟 componentDidMount 和 componentDidUpdateuseEffect(() => {console.log('组件已挂载或更新');// 模拟 componentWillUnmountreturn () => {console.log('组件将卸载');};}, [counter]); // 依赖项,只有当 counter 更新时,才会重新执行 useEffectreturn (<div><p>Counter: {counter}</p><button onClick={() => setCounter(counter + 1)}>增加计数</button></div>);
};export default MyFunctionComponent;
6.4 React 18 的新特性
React 18 引入了多个新特性,最显著的之一是 并发模式(Concurrent Mode),它改善了渲染性能,尤其是在 React 应用的响应式方面。虽然并发模式与生命周期方法的直接关系不大,但它会影响组件的挂载、更新和卸载过程。
React 18 还引入了 自动批量更新(Automatic Batching)和 Suspense 进一步增强了异步渲染的能力。这些新特性和生命周期方法并没有冲突,而是增强了现有的机制。
总结:
类组件:React 18 中,类组件的生命周期方法仍然有效,且与之前的版本一样。
函数组件:函数组件使用 useEffect 和其他 Hooks 来模拟传统的生命周期方法。
React 18 新特性:引入了并发模式、自动批量更新等,但它不会影响生命周期方法。
因此,如果你使用类组件,React 18 中依然可以使用传统的生命周期方法。如果使用函数组件,你可以通过 useEffect 来替代和模拟传统生命周期的行为。
相关文章:
React 生命周期完整指南
React 生命周期完整指南 1. 生命周期概述 1.1 React 16.3 之前的生命周期 初始化阶段 constructorcomponentWillMountrendercomponentDidMount 更新阶段 componentWillReceivePropsshouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate 卸载阶段 componentWil…...
python中os._exit(0) 强制关闭进程后来杀死线程
在 Python 中调用 os._exit(0) 会强制终止整个进程,包括所有正在运行的线程。以下是详细解释: os._exit(0) 的行为 立即终止进程:os._exit() 函数会立即终止当前进程,不会执行任何清理操作,如调用清理处理程序&#…...

LeetCode:257. 二叉树的所有路径
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:257. 二叉树的所有路径 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根…...

RSICV国产芯片之CHV208
1. 芯片选型分析的对比维度 分析或者对标应用的芯片替代思路 1.1 内核/主频/存储空间支持 内核能力/指令集支持(考虑工具链兼容性); 主频:对比计算能力是否满足基本要求 存储:内存--数据搬移空间决定数据运算的…...

理解神经网络
神经网络是一种模拟人类大脑工作方式的计算模型,是深度学习和机器学习领域的基础。 基本原理 神经网络的基本原理是模拟人脑神经系统的功能,通过多个节点(也叫神经元)的连接和计算,实现非线性模型的组合和输出。每个…...
Android 之 List 简述
一、简单创建方式 Android 开发中,列表有很多种类,如ArrayList、LinkedList、List、MutableList等,创建列表的方式如下所示: fun listDemo() {// 使用 listOf 创建不可变的空列表val list listOf<Int>()val list1 listOf…...
设计模式の中介者发布订阅备忘录模式
文章目录 前言一、中介者模式二、发布订阅模式三、备忘录模式 前言 本篇是关于设计模式中介者模式、观察者(发布-订阅)模式、以及备忘录模式的学习笔记。 一、中介者模式 中介者模式是一种行为型设计模式,其核心目的是为了减少对象之间的复杂…...

云手机群控能用来做什么?
随着云手机的发展,云手机群控技术逐渐从小众的游戏多开工具,发展为涵盖多个领域的智能操作平台。不论是手游搬砖、短视频运营,还是账号养成等场景,云手机群控都展现出了强大的应用潜力。本文将为大家详细解析云手机群控的应用场景…...

fpgafor循环语句使用
genvar i;//循环变量名称 generate for(i0;i<4;ii1)begin:tx//自己定义名称 //循环内容 end endgenerate12位的16进制乘以4就是48位位宽的2进制 因为 222*2(2^4)16...
【FastAPI】BaseHTTPMiddleware类
一、概述 在FastAPI中,BaseHTTPMiddleware 类是Starlette框架提供的一个抽象基类,它允许开发者基于HTTP请求/响应接口编写ASGI中间件。 这个类对于希望实现自定义中间件逻辑的开发者来说是非常重要的工具。 通过继承 BaseHTTPMiddleware 并实现特定的方…...

Solon v3.0.5 发布!(Spring 可以退休了吗?)
Solon 框架! 新一代,面向全场景的 Java 应用开发框架。从零开始构建(非 java-ee 架构),有灵活的接口规范与开放生态。 追求: 更快、更小、更简单提倡: 克制、高效、开放、生态 有什么特点&am…...
网络安全攻防演练中的常见计策
大家觉得有意义记得关注和点赞!!! 引言 在网络安全攻防演练里面,用于分析攻击者动机和行为的,国外的有基于攻击链分析的模型(如Cyber Kill Chain和ATT&CK)和基于威胁行为的模型(…...

SD卡模块布局布线设计
1、SD/TF/SIM卡的定义 2、SD/TF/SIM卡模块引脚定义以及图示 3、SD/TF/SIM卡接口布局和布线 4、小结 1、BGA两线交叉时,可以在源头将两线互相短路连接,然后再输出口删除一小节线,然后CHRLX/V,这样就可以换两条线的网络,…...
Flask-----SQLAlchemy教程
存session session[username] username # 存储数据到 session 取session username session.get(username) render_template return render_template(index.html, usernameAlice),渲染一个包含 username 变量的模板。 redirect return redirect(url_for(profil…...
STM32 高级 物联网通信之CAN通讯
目录 CAN通讯介绍 物理层 协议层 CAN的帧(报文)种类 1 数据帧(发送单元->接受单元) 2 远程帧(接受单元->发送单元) 3 错误帧(发送方发送数据错误会发送的状态帧) 4 过载帧(接收方放不下会发送到的状态帧) 5 帧间隔(状态) 数据帧介绍 远程帧介绍 C…...

“乡村探索者”:村旅游网站的移动应用开发
3.1 可行性分析 从三个不同的角度来分析,确保开发成功的前提是有可行性分析,只有进行提前分析,符合程序开发流程才不至于开发过程的中断。 3.1.1 技术可行性 在技术实现层次,分析了好几种技术实现方法,并且都有对应的成…...

前端案例---自定义鼠标右键菜单
之前右击出现默认的选项菜单,使用evt.preventDefault()把默认的去掉,然后自定义右击的样式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible"…...
浅谈归一化
在深度学习中,对网络层进行归一化(Normalization,简称Norm)是一个重要的技巧。常见的归一化方法包括批归一化(Batch Normalization)、层归一化(Layer Normalization)、实例归一化&am…...
lodash常用函数
文章目录 一、数组1、chunk分组2、difference、differenceBy、differenceWith3、findIndex4、intersection、intersectionBy、intersectionWith5、union、unionBy、unionWith 二、对象1、pick、omit 2、get、set三、数学1、sum、sumBy2、range 四、工具函数1、isEqual、isEmpty…...
触控算法总结
一、触控湿手指算法的具体实现原理涉及多个方面的技术和方法,主要包括以下几个关键点 1.电容变化检测 电容式触摸屏通过检测电容变化来确定触摸位置。当手指接触屏幕时,会引起电容的变化。然而,当手指湿润时,水分会影响电容值,导致触摸屏误判成无法正确识别触控点 2.噪声过滤: …...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...