🌿 React 生命周期详解:从创建到销毁的完整旅程
在使用 React 构建组件化应用的过程中,我们经常会听到一个重要的概念——生命周期(Lifecycle)。
生命周期是指一个组件从创建(Mounting)、更新(Updating)到卸载(Unmounting)的整个过程。
React 在不同阶段提供了一系列 生命周期方法(Lifecycle Methods),让我们有机会在合适的时机执行副作用操作,比如发起网络请求、操作 DOM、保存状态等。
🧩 一、React 生命周期总览
React 组件的生命周期可以分为三个阶段:
| 阶段 | 说明 | 
|---|---|
| 挂载(Mounting) | 组件被创建并插入到 DOM 中 | 
| 更新(Updating) | 当组件的 state 或 props 发生变化时重新渲染 | 
| 卸载(Unmounting) | 组件从 DOM 中被移除 | 
对于类组件(Class Component)和函数组件(Function Component,Hooks),它们的生命周期表现有所不同。
🧱 二、类组件生命周期详解
React 16 之后,类组件的生命周期主要包括以下几个方法:
1. 挂载阶段
| 方法 | 调用时机 | 用途 | 
|---|---|---|
constructor() | 
组件被创建时调用 | 初始化 state、绑定方法 | 
static getDerivedStateFromProps() | 
在 render() 前调用 | 
根据 props 更新 state | 
render() | 
渲染 UI | 返回要显示的 JSX | 
componentDidMount() | 
组件挂载后调用 | 执行副作用(如请求数据、操作 DOM) | 
constructor(props)
构造函数,在组件创建时调用,用于初始化状态和绑定事件处理函数。
在构造函数中调用 super(props) 来调用父类的构造函数,并将 props 传递给父类。
初始化组件的状态可以通过 this.state = { } 实现。static getDerivedStateFromProps(props, state)
当组件接收到新的 props 时调用,在渲染之前执行。
用于根据新的 props 计算并更新组件的状态。
应返回一个对象来更新状态,或者返回 null 来表示不需要更新状态。render()
必需的生命周期方法,用于渲染组件的 UI。
应返回一个 React 元素,描述组件的输出。
不应该在这个方法中修改组件的状态或执行副作用操作。componentDidMount()
在组件的初始渲染之后立即被调用的
通常在这个方法中执行一些初始化操作(比如发起网络请求、订阅事件、获取初始数据)
这个方法只会在组件的生命周期中被调用一次,因此适合进行一次性的初始化工作
示例:
1  | class Example extends React.Component {  | 
📌 执行顺序:constructor → render → componentDidMount
2. 更新阶段
当组件的 props 或 state 发生变化 时,组件会重新渲染。主要生命周期方法如下:
| 方法 | 调用时机 | 用途 | 
|---|---|---|
static getDerivedStateFromProps() | 
每次渲染前调用 | 根据 props 更新 state | 
shouldComponentUpdate() | 
决定是否重新渲染 | 性能优化 | 
render() | 
重新渲染组件 | 更新 UI | 
getSnapshotBeforeUpdate() | 
更新前获取 DOM 状态 | 如滚动位置等 | 
componentDidUpdate() | 
更新完成后调用 | 发起请求、操作更新后的 DOM | 
shouldComponentUpdate(nextProps, nextState)
在组件接收到新的 props 或者 state 时被调用,在渲染之前执行。
可以根据新的 props 或者 state 决定是否需要重新渲染组件。
默认返回 true,表示组件将会重新渲染,可以通过返回 false 来阻止重新渲染,以提升性能。render()
必需的生命周期方法,用于渲染组件的 UI。
应返回一个 React 元素,描述组件的输出。
不应该在这个方法中修改组件的状态或执行副作用操作。getSnapshotBeforeUpdate(prevProps, prevState)
在最新的渲染输出被提交到 DOM 之前调用。
用于获取更新前的 DOM 快照或执行一些 DOM 操作。
返回的值将作为 componentDidUpdate 方法的第三个参数传递。componentDidUpdate(prevProps, prevState, snapshot)
在组件更新完成后立即调用。
通常用于执行一些副作用操作,比如更新后的 DOM 操作、发送网络请求等。
可以访问到更新之前的 props、state,以及通过 getSnapshotBeforeUpdate 返回的值。
示例:
1  | componentDidUpdate(prevProps, prevState) {  | 
📌 执行顺序:getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate
3. 卸载阶段
| 方法 | 调用时机 | 用途 | 
|---|---|---|
componentWillUnmount() | 
组件即将卸载时调用 | 清除定时器、取消订阅、释放资源等 | 
componentWillUnmount()
在组件即将被销毁并从 DOM 中移除之前调用。
用于执行一些清理工作,比如取消订阅、清除定时器等。
在这个方法中不能调用 setState,因为组件即将被销毁。
示例:
1  | componentWillUnmount() {  | 
⚛️ 三、函数组件的生命周期(Hooks)
函数组件没有传统的生命周期方法,而是通过 React Hooks(如 useEffect)实现相同的效果。
1. 模拟挂载和卸载
1  | import { useEffect } from 'react';  | 
📌 useEffect 第二个参数为 [] 时,等价于:
componentDidMountcomponentWillUnmount
2. 模拟更新
1  | useEffect(() => {  | 
📌 当依赖项 count 改变时触发,等价于:
componentDidUpdate
3. 多个 useEffect 拆分逻辑
在函数组件中,我们可以声明多个 useEffect 来分别管理不同的副作用逻辑:
1  | useEffect(() => {  | 
🧠 四、生命周期与 Fiber 架构的关系
React 16 引入了 Fiber 架构,它让生命周期的执行变得更“可中断”、“可恢复”。
这意味着:
- 某些生命周期方法(如 
componentWillMount、componentWillUpdate)可能在异步渲染中被多次调用; - 因此它们被标记为 不安全生命周期(Unsafe Lifecycle)。
 
推荐使用以下“安全生命周期”:
- ✅ 
componentDidMount - ✅ 
componentDidUpdate - ✅ 
componentWillUnmount - ✅ 
getDerivedStateFromProps - ✅ 
getSnapshotBeforeUpdate 
🧩 五、生命周期对比图
以下是常见生命周期的执行顺序(简化版):
1  | 挂载阶段:  | 
🔍 六、总结对比表
| 功能 | 类组件 | 函数组件 | 
|---|---|---|
| 挂载 | componentDidMount() | 
useEffect(() => {...}, []) | 
| 更新 | componentDidUpdate() | 
useEffect(() => {...}, [dep]) | 
| 卸载 | componentWillUnmount() | 
useEffect(() => return {...}, []) | 
| 性能优化 | shouldComponentUpdate() | 
React.memo() | 
💬 七、结语
理解生命周期,是深入掌握 React 的关键。
在类组件中,我们通过生命周期方法控制组件行为;
而在函数组件中,我们用 useEffect、useMemo、useLayoutEffect 等 Hooks 来优雅地管理副作用。
掌握生命周期,你就能更好地:
- 控制组件的行为;
 - 避免不必要的渲染;
 - 编写更高效、更易维护的代码。