news 2026/11/3 17:27:43

React 生命周期详解:从挂载到卸载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React 生命周期详解:从挂载到卸载

React 生命周期详解:从挂载到卸载

React 组件的生命周期(Lifecycle)是指组件从创建到销毁的整个过程,包括挂载、更新和卸载三个主要阶段。这套机制允许开发者在组件的不同生命周期节点注入自定义逻辑,如初始化状态、请求数据、清理资源等。

关键点:

  • 主要针对类组件:React 16.3+ 引入 Hooks 后,函数组件通过useEffect等 Hook 模拟生命周期。但本文重点讲解类组件的经典生命周期(基于 React 18+)。
  • 已弃用方法:React 17+ 标记了componentWillMount、componentWillReceiveProps、componentWillUpdate为 UNSAFE_(不推荐使用,可能在未来版本移除)。
  • 异步渲染:React 16+ 支持异步渲染,生命周期方法调用顺序可能因 Fiber 架构而略有变化,但整体流程一致。
  • Hooks 替代:函数组件更推荐,使用useEffect、useState等实现类似功能。

下面按时间线(从挂载到卸载)详细拆解每个阶段,包括方法调用顺序、用途、代码示例和注意事项。

1. 挂载阶段(Mounting):组件首次渲染到 DOM

这一阶段从组件实例化开始,到插入 DOM 结束。顺序固定。

方法名称调用时机用途 / 常见操作是否能访问 DOM异步渲染影响
constructor()组件实例化时(props 传入前)初始化 state、绑定方法(this.xxx = this.xxx.bind(this))否无
static getDerivedStateFromProps(props, state)constructor 后 / render 前(静态方法)从 props 派生 state(很少用)否无
render()所有准备就绪后返回 JSX / React 元素(纯函数,不能有副作用)否—
componentDidMount()render 后,组件已插入 DOM请求数据、添加事件监听、setState(初始化后更新)是无

代码示例:

class MyComponent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; this.handleClick = this.handleClick.bind(this); // 绑定方法 } static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.initialCount !== prevState.count) { return { count: nextProps.initialCount }; // 从 props 更新 state } return null; } componentDidMount() { // 发起 API 请求 fetch('/api/data').then(res => this.setState({ data: res })); document.addEventListener('click', this.handleClick); // 添加全局监听 } render() { return <div>Count: {this.state.count}</div>; } }

注意:

  • 避免在 constructor 中调用 setState(props 还没初始化)。
  • componentDidMount 是请求数据的黄金时机(不会阻塞渲染)。
  • 已弃用:UNSAFE_componentWillMount(用 constructor 或 getDerivedStateFromProps 代替)。
2. 更新阶段(Updating):组件 props/state 变化时

当 props/state 变化、父组件重渲染或 forceUpdate() 时触发。顺序类似挂载,但多了一些更新前检查。

方法名称调用时机用途 / 常见操作是否能访问 DOM异步渲染影响
static getDerivedStateFromProps(props, state)props/state 变化后,render 前从新 props 更新 state否无
shouldComponentUpdate(nextProps, nextState)getDerivedStateFromProps 后性能优化:返回 false 阻止渲染(PureComponent 默认实现)否无
render()shouldComponentUpdate 返回 true 后返回新 JSX否—
getSnapshotBeforeUpdate(prevProps, prevState)render 后,DOM 更新前捕获 DOM 状态(如滚动位置)返回给 componentDidUpdate是无
componentDidUpdate(prevProps, prevState, snapshot)DOM 更新后更新后操作(如动画、请求新数据)是无

代码示例:

class MyComponent extends React.Component { shouldComponentUpdate(nextProps, nextState) { return nextProps.value !== this.props.value; // 浅比较,避免不必要渲染 } getSnapshotBeforeUpdate(prevProps, prevState) { // 捕获滚动位置 return document.getElementById('scroll-container').scrollTop; } componentDidUpdate(prevProps, prevState, snapshot) { if (this.props.value !== prevProps.value) { // 根据 snapshot 恢复滚动位置 document.getElementById('scroll-container').scrollTop = snapshot; // 或发起新请求 fetch(`/api/update?newValue=${this.props.value}`); } } render() { return <div>Value: {this.props.value}</div>; } }

注意:

  • shouldComponentUpdate 是性能调优的关键(但不要过度使用)。
  • 已弃用:UNSAFE_componentWillReceiveProps、UNSAFE_componentWillUpdate(用 getDerivedStateFromProps / getSnapshotBeforeUpdate 代替)。
  • componentDidUpdate 避免直接 setState(防止无限循环),用条件判断。
3. 卸载阶段(Unmounting):组件从 DOM 移除

当组件被移除(父组件不渲染它)时触发。只有一个方法。

方法名称调用时机用途 / 常见操作是否能访问 DOM异步渲染影响
componentWillUnmount()组件即将从 DOM 移除前清理资源:移除事件监听、取消定时器、关闭连接是无

代码示例:

class MyComponent extends React.Component { componentDidMount() { this.timer = setInterval(() => console.log('tick'), 1000); document.addEventListener('click', this.handleClick); } componentWillUnmount() { clearInterval(this.timer); // 清理定时器 document.removeEventListener('click', this.handleClick); // 移除监听 // 关闭 WebSocket 等 } render() { return <div>Unmounting Example</div>; } }

注意:

  • 这里是清理资源的唯一时机(防止内存泄漏)。
  • 不要在这里 setState(组件已卸载)。
  • 已弃用:无(但老版本有 componentWillUnmount 的 UNSAFE_ 变体)。
4. 函数组件的生命周期(Hooks 模拟,2025 主流写法)

类组件生命周期正逐渐被 Hooks 取代。Hooks 更简洁、复用性强。

类组件方法Hooks 等价物备注
constructoruseState 初始值—
getDerivedStateFromPropsuseEffect + 依赖数组—
componentDidMountuseEffect(() => { … }, [])空依赖数组
shouldComponentUpdateReact.memo / useMemo—
componentDidUpdateuseEffect(() => { … }, [deps])非空依赖
componentWillUnmountuseEffect(() => { return cleanup; }, [deps])返回清理函数

Hooks 示例(模拟类组件):

import { useState, useEffect } from 'react'; function MyFunctionalComponent({ value }) { const [count, setCount] = useState(0); useEffect(() => { // componentDidMount + componentDidUpdate fetch(`/api/data?value=${value}`).then(res => setCount(res.count)); return () => { // componentWillUnmount console.log('清理资源'); }; }, [value]); // 依赖 value 变化 return <div>Count: {count}</div>; }

注意:useEffect 的依赖数组是关键(空数组 = 只挂载时执行;无数组 = 每次渲染都执行)。

5. 常见问题与最佳实践
  • 无限循环:componentDidUpdate / useEffect 中无条件 setState → 无限渲染。
  • 性能优化:用 shouldComponentUpdate / React.memo 避免子组件不必要重渲染。
  • 异步问题:setState 是异步的(用回调形式处理)。
  • 迁移建议:新项目优先 Hooks(函数组件);老项目类组件可渐进迁移。
  • 调试工具:React DevTools 高亮组件渲染顺序和生命周期钩子。

掌握这些,你就能在 React 项目中精准控制组件行为!如果想看具体 Hooks 示例或某个方法的深度代码实战,告诉我,我们继续。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 2:54:07

java集合框架

Java 集合框架&#xff08;Java Collections Framework&#xff09;完整梳理 Java 集合框架是 Java 开发中最核心、最常用的部分之一&#xff0c;几乎所有的业务代码、算法实现、数据处理都离不开它。 下面从整体架构 → 核心接口 → 常用实现类 → 线程安全方案 → 面试高频考…

作者头像 李华
网站建设 2026/11/2 2:54:12

springboot宠物医院管理系统绿色vue

目录 系统概述技术栈核心功能模块绿色设计特点扩展性 开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 系统概述 SpringBoot宠物医院管理系统结合Vue.js前端框架&#xff0c;构建高效、用户友好的宠物医疗管理平台。系统采用前…

作者头像 李华
网站建设 2026/11/3 13:56:44

springboot宠物领养寄养兽医预约系统vue

目录 系统概述技术架构核心功能扩展特性部署与优化 开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 系统概述 SpringBoot宠物领养寄养兽医预约系统结合Vue前端框架&#xff0c;构建了一个全栈式的宠物服务管理平台。系统涵盖宠…

作者头像 李华
网站建设 2026/11/2 3:06:31

【Django毕设全套源码+文档】基于Django框架的物资配送管理系统的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/11/2 3:06:31

error_log默认格式的庖丁解牛

error_log 默认格式 是 PHP 内置错误日志的 标准文本格式&#xff0c;由 Zend 引擎直接生成&#xff0c;无需任何日志库&#xff08;如 Monolog&#xff09;。它虽简单&#xff0c;却包含 时间、错误类型、消息、文件、行号 五大核心要素&#xff0c;是排查 PHP 错误的第一道防…

作者头像 李华