深入理解 React 组件的生命周期:从创建到销毁的全过程
React 作为当今最流行的前端框架之一,其组件生命周期是每个 React 开发者必须掌握的核心概念。本文将全面剖析 React 组件的生命周期,包括类组件的各个生命周期方法和函数组件如何使用 Hooks 模拟生命周期行为,帮助开发者编写更高效、更健壮的 React 应用。

一、React 组件生命周期概述
React 组件的生命周期指的是一个组件从创建、更新到销毁的整个过程。在这个过程中,React 提供了许多"生命周期方法",允许开发者在特定的阶段执行自定义代码。理解这些生命周期方法对于控制组件行为、优化性能以及管理副作用至关重要。
React 的生命周期可以分为三个主要阶段:
-
挂载阶段(Mounting):组件被创建并插入到 DOM 中
-
更新阶段(Updating):组件的 props 或 state 发生变化时的重新渲染过程
-
卸载阶段(Unmounting):组件从 DOM 中移除
此外,React 16 还引入了错误处理生命周期方法,用于捕获和处理组件树中的 JavaScript 错误。

二、类组件的生命周期详解
1. 挂载阶段(Mounting)
挂载阶段是组件第一次被创建并插入到 DOM 中的过程,包含以下生命周期方法:
constructor()
constructor(props) {super(props);this.state = { count: 0 };this.handleClick = this.handleClick.bind(this);
}
-
最先执行的生命周期方法
-
必须调用
super(props),否则this.props将会是 undefined -
唯一可以直接修改
this.state的地方 -
用于初始化 state 和绑定事件处理方法
static getDerivedStateFromProps()
static getDerivedStateFromProps(props, state) {if (props.value !== state.prevValue) {return {value: props.value,prevValue: props.value};}return null;
}
-
在 render 方法之前调用,无论是初始挂载还是后续更新
-
应返回一个对象来更新 state,或返回 null 不更新
-
用于 state 依赖于 props 变化的罕见情况
-
此方法无权访问组件实例(即不能使用 this)
render()
render() {return <div>{this.state.count}</div>;
}
-
类组件中唯一必须实现的方法
-
应该是一个纯函数,不修改组件状态,不与浏览器交互
-
返回以下类型之一:
-
React 元素(JSX)
-
数组或 fragments
-
Portals
-
字符串或数值(渲染为文本节点)
-
布尔值或 null(不渲染任何内容)
-
componentDidMount()
componentDidMount() {// 典型用法:fetchData().then(data => this.setState({ data }));// 或this.subscription = dataSource.subscribe(this.handleDataChange);
}
-
组件挂载(插入 DOM 树)后立即调用
-
适合执行有副作用的操作:
-
网络请求
-
设置订阅
-
手动操作 DOM
-
-
可以在此处直接调用 setState(),但会触发额外渲染
2. 更新阶段(Updating)
当组件的 props 或 state 发生变化时,会触发更新阶段的生命周期方法:
static getDerivedStateFromProps()
-
同挂载阶段,在每次渲染前调用
shouldComponentUpdate()
shouldComponentUpdate(nextProps, nextState) {// 只有当count变化时才重新渲染return nextState.count !== this.state.count;
}
-
决定组件是否应该更新
-
返回 false 可以阻止组件重新渲染
-
主要用于性能优化
-
不建议深层比较或使用 JSON.stringify(),影响性能
-
考虑使用 PureComponent 替代手动实现
render()
-
同挂载阶段
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate(prevProps, prevState) {if (prevProps.items.length < this.props.items.length) {const list = this.listRef.current;return list.scrollHeight - list.scrollTop;}return null;
}
-
在最近一次渲染输出(提交到 DOM 节点)之前调用
-
使得组件能在 DOM 变化前捕获一些信息(如滚动位置)
-
返回值将作为 componentDidUpdate() 的第三个参数
componentDidUpdate()
componentDidUpdate(prevProps, prevState, snapshot) {if (this.props.userID !== prevProps.userID) {this.fetchData(this.props.userID);}if (snapshot !== null) {const list = this.listRef.current;list.scrollTop = list.scrollHeight - snapshot;}
}
-
更新完成后调用(首次渲染不会执行)
-
适合执行有副作用的操作:
-
网络请求(需比较 props)
-
DOM 操作
-
-
可以调用 setState(),但必须包裹在条件语句中,否则会导致无限循环
3. 卸载阶段(Unmounting)
componentWillUnmount()
componentWillUnmount() {clearInterval(this.timerID);this.subscription.unsubscribe();
}
-
组件卸载及销毁前调用
-
用于执行必要的清理操作:
-
清除定时器
-
取消网络请求
-
清理订阅
-
-
不应调用 setState(),因为组件永远不会重新渲染
4. 错误处理
React 16 引入了错误边界的概念,用于捕获子组件树中的 JavaScript 错误。
static getDerivedStateFromError()
static getDerivedStateFromError(error) {return { hasError: true };
}
-
在后代组件抛出错误后被调用
-
接收错误作为参数
-
应返回一个状态对象以更新 state,用于渲染备用 UI
componentDidCatch()
componentDidCatch(error, info) {logErrorToService(error, info.componentStack);
}
-
在后代组件抛出错误后被调用
-
接收两个参数:
-
error - 抛出的错误
-
info - 包含 componentStack 键的对象
-
-
用于记录错误信息
三、函数组件的"生命周期"
随着 React Hooks 的引入,函数组件现在也能实现类组件的生命周期功能。以下是常用 Hooks 与生命周期方法的对应关系:
useState - 状态管理
const [count, setCount] = useState(0);
-
相当于类组件中的 this.state 和 this.setState
-
可以在函数组件中添加局部 state
useEffect - 副作用管理
useEffect(() => {// 相当于 componentDidMount 和 componentDidUpdatedocument.title = `You clicked ${count} times`;return () => {// 相当于 componentWillUnmount// 清理函数};
}, [count]); // 仅在 count 更改时更新
-
组合了 componentDidMount, componentDidUpdate 和 componentWillUnmount
-
第一个参数是 effect 函数,第二个参数是依赖数组
-
返回的函数是清理函数,在组件卸载时执行
useLayoutEffect
useLayoutEffect(() => {// 在 DOM 更新后同步执行const { width } = node.getBoundingClientRect();setWidth(width);
});
-
与 useEffect 签名相同,但调用时机不同
-
在 DOM 变更后同步触发
-
适用于需要读取 DOM 布局并同步重新渲染的情况
useMemo 和 useCallback - 性能优化
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
-
相当于 shouldComponentUpdate 的优化
-
用于避免不必要的计算和渲染
四、新旧生命周期对比与最佳实践
React 16.3 对生命周期方法进行了重大调整,废弃了一些不安全的生命周期方法:
废弃的方法:
-
componentWillMount
-
componentWillReceiveProps
-
componentWillUpdate
这些方法被标记为不安全主要是因为:
-
它们经常被误用和滥用
-
在异步渲染中可能导致问题
-
容易引入副作用和错误
最佳实践建议:
-
将数据获取移到 componentDidMount 或 useEffect 中
-
使用 getDerivedStateFromProps 替代 componentWillReceiveProps
-
使用 getSnapshotBeforeUpdate 替代 componentWillUpdate
-
考虑使用函数组件和 Hooks 替代类组件
-
谨慎使用派生 state,多数情况下可以通过提升 state 或受控组件解决
五、实际应用场景示例
场景1:数据获取
class UserProfile extends React.Component {state = { user: null, loading: true };async componentDidMount() {const user = await fetchUser(this.props.userId);this.setState({ user, loading: false });}async componentDidUpdate(prevProps) {if (this.props.userId !== prevProps.userId) {this.setState({ loading: true });const user = await fetchUser(this.props.userId);this.setState({ user, loading: false });}}componentWillUnmount() {// 取消可能的未完成请求}render() {// 渲染用户信息}
}
场景2:滚动位置恢复
class ScrollList extends React.Component {getSnapshotBeforeUpdate(prevProps) {if (prevProps.items.length < this.props.items.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;}}render() {return (<div ref={this.listRef}>{/* 列表内容 */}</div>);}
}
场景3:错误边界
class ErrorBoundary extends React.Component {state = { hasError: false };static getDerivedStateFromError(error) {return { hasError: true };}componentDidCatch(error, info) {logErrorToService(error, info.componentStack);}render() {if (this.state.hasError) {return <h1>Something went wrong.</h1>;}return this.props.children; }
}
总结
React 组件的生命周期是 React 应用的核心机制,理解这些生命周期方法对于构建高效、可靠的 React 应用至关重要。随着 React 的发展,生命周期方法也在不断演进,从类组件的各种生命周期方法到函数组件的 Hooks,React 提供了更灵活、更简洁的方式来管理组件的生命周期。
对于新项目,建议优先考虑使用函数组件和 Hooks,它们提供了更简洁的代码组织和更强大的组合能力。对于现有项目,了解类组件的生命周期仍然很重要,特别是在维护老代码时。
记住,生命周期方法是你控制组件行为的工具,正确使用它们可以:
-
优化性能
-
管理副作用
-
处理错误
-
保持代码整洁和可维护
通过掌握 React 组件的生命周期,你将能够构建更强大、更可靠的 React 应用程序。
相关文章:
深入理解 React 组件的生命周期:从创建到销毁的全过程
React 作为当今最流行的前端框架之一,其组件生命周期是每个 React 开发者必须掌握的核心概念。本文将全面剖析 React 组件的生命周期,包括类组件的各个生命周期方法和函数组件如何使用 Hooks 模拟生命周期行为,帮助开发者编写更高效、更健壮的…...
基础数学知识-概率论
文章目录 1. 随机事件和概率1. 事件运算规律2. 条件概率3. 事件独立性4. 五大公式5. 古典型概率6. 几何型概率7. n重伯努利试验2. 随机变量与分布1.离散型随机变量2. 连续型随机变量3. 常见分布4. TODO4. 随机变量的数学特征1. 数学期望2. 方差3. 常见分布期望与方差 -- TODO4.…...
OpenCV 图形API(44)颜色空间转换-----将图像从 BGR 色彩空间转换为 RGB 色彩空间函数BGR2RGB()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将图像从BGR色彩空间转换为RGB色彩空间。 该函数将输入图像从BGR色彩空间转换为RGB。B、G和R通道值的常规范围是0到255。 输出图像是8位无符号3通…...
2025年CMS安全(面试题)
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
配置nginx服务,通过多ip区分多网站
首先关闭防火墙,setenforce 0 关过了,不截图了 多IP,首先配置多个IP地址 可以在vm增加虚拟网卡,也可以在同一网卡配置多个IP,我用第一种 记得点确定 查看新的虚拟网卡IP 没有IP,配置一个 安装nginx 写配置 server{listen 192.168.214.130:80;root /www/ip/130; # 资源根目…...
[k8s实战]Containerd 1.7.2 离线安装与配置全指南(生产级优化)
[k8s实战]Containerd 1.7.2 离线安装与配置全指南(生产级优化) 摘要:本文详细讲解在无外网环境下部署 Containerd 1.7.2 容器运行时的完整流程,涵盖二进制包安装、私有镜像仓库配置、Systemd服务集成等关键步骤,并提供…...
C++中const与constexpr的区别
在C中,const和constexpr都用于定义常量,但它们的用途和行为有显著区别: ### 1. **初始化时机** - **const**:表示变量是只读的,但其值可以在**编译时或运行时**初始化。 cpp const int a 5; // 编译…...
解决Windows安全中心显示空白页面
1、电脑重装系统后,发现原本一些软件打不开了,电脑莫名认为有病毒,自动删除插件。附图。 2、第一反应是电脑防火墙的原因,默认威胁防护识别到了病毒软件,自动删除。在开始屏幕搜Windows安全中心,打开之后发…...
三国战纪119通关笔记
文章目录 诸葛一币通关孙姬马王夏侯渊孟优夏侯惇张辽貂蝉吕蒙沙摩柯破阵及吕布陆逊左慈(跳)许褚黄盖彻里吉(跳)魏延(跳)司马懿曹操道具的安排道具-天师符(废弃)道具-九节杖道具-援军令(废弃)道具-土雷(废弃) 笔者是个菜鸡,什么天王难度无伤,天王难度5禁什…...
Android audio系统五 AudioPolicy 策略配置详解
引用:Android 音频策略配置文件解析流程 audio_policy_configuration.xml 是 Android 音频系统的核心配置文件,它定义了音频硬件接口、设备路由和基本策略。下面我将详细介绍这个文件的结构、关键配置项和实际应用。audio_policy_configuration.xml 是 …...
【MQ篇】初识MQ!
目录 一、什么是MQ?简单来说就是个“快递中转站” 📦二、为什么要用MQ?用了它,好处多多!🤩三、MQ的应用场景:各行各业都能用!🌍四、MQ的优缺点:硬币的两面&am…...
2、SpringAI接入ChatGPT与微服务整合
2、SpringAI接入ChatGPT与微服务整合 小薛博客AI 大模型资料 1、SpringAI简介 https://spring.io/projects/spring-ai Spring AI是一个人工智能工程的应用框架。其目标是将Spring生态系统的设计原则(如可移植性和模块化设计)应用于人工智能领域&#…...
【Linux】多进程任务模块
创建多个进程,同时完成任务 task.c #include <sys/types.h> #include <unistd.h> #include<stdio.h> #include <sys/wait.h> int create_process_tasks(Task_fun_t tasks[],int tsak_cnt) {pid_t pid;int i 0;for(i 0;i < 4;i){pid …...
榕壹云预约咨询系统:基于ThinkPHP+MySQL+UniApp打造的灵活预约小程序解决方案
数字化咨询场景的痛点与解决方案 在心理咨询、医疗问诊、法律咨询等需要预约服务的场景中,传统线下预约存在效率低、管理复杂、资源分配不均等问题。榕壹云预约咨询系统基于ThinkPHPMySQLUniApp技术栈开发,为咨询类行业提供了一套高效、安全、可扩展的数…...
鸿蒙NEXT开发LRUCache缓存工具类(单例模式)(ArkTs)
import { util } from kit.ArkTS;/*** LRUCache缓存工具类(单例模式)* author 鸿蒙布道师* since 2025/04/21*/ export class LRUCacheUtil {private static instance: LRUCacheUtil;private lruCache: util.LRUCache<string, any>;/*** 私有构造函…...
opencv 图像矫正的原理
图像矫正的原理是透视变换,下面来介绍一下透视变换的概念。 听名字有点熟,我们在图像旋转里接触过仿射变换,知道仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换,…...
计算机前沿技术课程论文 K-means算法在图像处理的应用
K-means算法在图像处理的应用 这是本人在计算机前沿技术课程中的课程论文文章,为了方便大家参考学习,我把完整的论文word文档发到了我的资源里,有需要的可以自取。 点击完整资源链接 目录 K-means算法在图像处理的应用摘要:引言1…...
【股票数据API接口37】如何获取股票指数实时数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
如今,量化分析在股市领域风靡一时,其核心要素在于数据,获取股票数据,是踏上量化分析之路的第一步。你可以选择亲手编写爬虫来抓取,但更便捷的方式,莫过于利用专业的股票数据API接口。自编爬虫虽零成本&a…...
【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(17):PlanReactExecutor
CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。 这篇文章剖析一下 CangjieMagic 框架中的 PlanReactExecutor。 1 PlanReactExecutor的工作原理 #mermaid-svg-OqJUCSoxZkzylbDY…...
docker harbor私有仓库登录报错
docker harbor私有仓库登录报错如下: [rootsrv-1 ~]# docker login -u user1 -p pwd1 harbor.chinacloudapi.cn WARNING! Using --password via the CLI is insecure. Use --password-stdin. Error response from daemon: Get "https://harbor.chinacloudapi.…...
IQ信号和实信号的关系与转换的matlab实现
IQ信号 IQ信号通常是指两路正交的信号(I路和Q路),在实际信号采样中,通常会进行IQ采样,将实信号转换为复基带信号进行存储。 IQ信号转实信号 IQ信号转为实信号,其实就是将IQ两路正交信号通过上变频合并为一个实数的带通信号,这通常在通信系统中用于将基带信号调制到载…...
WSL2-Ubuntu22.04安装URSim5.21.3
WSL2-Ubuntu22.04安装URSim5.21.3 准备安装启动 准备 名称版本WSL2Ubuntu22.04URSim5.21.3VcXsrvNaN WSL2安装与可视化请见这篇:WSL2-Ubuntu22.04-配置。 安装 我们是wsl2-ubuntu22.04,所以安装Linux版本的URSim,下载之前需要注册一下,即…...
blender 录课键位显示插件(图文傻瓜式安装)
1、下载 点击这个链接进行下载https://github.com/nutti/Screencast-Keys 下载好不用解压 2、安装 打开blender进行安装 点击编辑选择偏好设置 选择插件再点击这个下箭头 选择从磁盘安装 然后找到自己刚刚下载好的,点击从磁盘安装 安装完成后勾选上插件 …...
天翼云手机断开连接2小时关机
2025-04-21 天翼云手机断开连接2小时自动 天翼云手机 4元1个月 天翼云手机永不关机 天翼云手机不休眠 天翼云手机断开连接时,界面显示:离线运行,2小时后自动关机 电脑每小时自动连接一次 手机每小时自动连接一次...
基于 FFmpeg 的音视频处理基础原理与实验探究
目录 1 基本知识1.1 解封装1.2 AAC和ADTS说明 1.3 H2641.3.1 H264编码结构解析1.3.2 NALU1.3.2 分类 2 实验1 探究音视频信息2.1 重要结构体介绍2.2 相关的API 3 实验二 提取AAC数据4 实验三 提取h264 1 基本知识 1.1 解封装 封装的逆向操作:封装是把音频流、视频流…...
【Rust 精进之路之第5篇-数据基石·下】复合类型:元组 (Tuple) 与数组 (Array) 的定长世界
系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:从原子到分子——组合的力量 在上一篇【数据基石上】中,我们仔细研究了 Rust 的四种基本标量类型࿱…...
【前端样式】用 aspect-ratio 实现等比容器:视频封面与图片占位的终极解决方案
在网页开发中,处理视频封面、图片卡片等需要固定比例的容器一直是前端工程师的必修课。本文将以 aspect-ratio 属性为核心,深入探讨如何优雅实现等比容器,并通过完整代码示例和常见问题解析,助你彻底掌握这一现代布局利器。 目录…...
【网络安全】OWASP 十大漏洞
1. OWASP 十大漏洞 为了应对未来的风险,安全专业人员需要随时掌握最新信息。之前,您了解了CVE 列表,这是一个公开的已知漏洞和暴露列表。CVE 列表是全球安全社区相互共享信息的重要信息来源。 在本文中,您将了解安全专业人士参考…...
我用deepseek做了一个提取压缩文件夹下pdf和word文件工具
由于最近需要把大量的压缩文件的pdf和word文件统一复制到一个文件夹中。 我们一般正常操作方式的是把一个压缩文件一个一个解压,然后在把一个的解压好的文件夹下文件复制到另外一个文件夹中。 这个也需太繁琐了,从以往统计的需要花费两个小时间&#x…...
【Docker】在容器中使用 NVIDIA GPU
解决容器 GPU 设备映射问题,实现 AI 应用加速 🔗 官方文档:NVIDIA Container Toolkit GitHub 常见错误排查 若在运行测试容器时遇到以下错误: docker: Error response from daemon: could not select device driver ""…...
