元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
React基础
▶
环境搭建
使用Create React App
Webpack基础配置
Babel转换配置
▶
JSX核心
JSX语法基础
JSX表达式使用
JSX与HTML差异
▶
组件入门
函数组件编写
类组件结构
组件组合模式
▶
核心概念
▶
Props机制
Props传递与接收
PropTypes类型检查
默认Props设置
▶
State管理
useState使用
setState机制
状态提升
▶
生命周期
类组件生命周期
useEffect使用
依赖项数组作用
▶
进阶实践
▶
路由管理
React Router安装
基本路由配置
动态路由参数
▶
状态管理
Context API使用
Redux核心概念
Redux Toolkit实践
▶
性能优化
memo使用
useCallback应用
代码分割实践
发布时间:
2025-03-22 12:57
↑
☰
# 类组件生命周期 本文将详细介绍React类组件的生命周期,帮助你理解组件从创建到销毁的整个过程。 ## 生命周期概述 React类组件的生命周期可以分为三个主要阶段: 1. 挂载阶段(Mounting) 2. 更新阶段(Updating) 3. 卸载阶段(Unmounting) ## 挂载阶段 组件实例被创建并插入DOM时,会依次调用以下方法: ### 1. constructor() ```javascript class Example extends React.Component { constructor(props) { super(props); // 必须调用super(props) this.state = { count: 0 }; this.handleClick = this.handleClick.bind(this); } } ``` 构造函数主要用于: - 初始化state - 绑定事件处理方法 - 不应在此执行副作用或订阅 ### 2. static getDerivedStateFromProps() ```javascript class Example extends React.Component { static getDerivedStateFromProps(props, state) { if (props.count !== state.lastCount) { return { count: props.count, lastCount: props.count }; } return null; } } ``` 这个方法用于: - 根据props更新state - 返回null或state对象 - 是静态方法,不能访问this ### 3. render() ```javascript class Example extends React.Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.state.content}</p> </div> ); } } ``` render方法: - 是类组件中唯一必须实现的方法 - 应该是纯函数 - 不应该修改state或直接与浏览器交互 ### 4. componentDidMount() ```javascript class Example extends React.Component { componentDidMount() { // 适合执行副作用的地方 this.fetchData(); this.subscribeToEvents(); } fetchData() { fetch('api/data') .then(response => response.json()) .then(data => this.setState({ data })); } } ``` 这个方法用于: - 执行副作用(如API调用) - 添加订阅 - 直接操作DOM ## 更新阶段 当组件的props或state发生变化时,会依次调用以下方法: ### 1. static getDerivedStateFromProps() 与挂载阶段相同。 ### 2. shouldComponentUpdate() ```javascript class Example extends React.Component { shouldComponentUpdate(nextProps, nextState) { // 性能优化:只在需要时更新 return ( this.props.value !== nextProps.value || this.state.count !== nextState.count ); } } ``` 用于: - 性能优化 - 控制组件是否重新渲染 - 返回false可以阻止更新 ### 3. render() 与挂载阶段相同。 ### 4. getSnapshotBeforeUpdate() ```javascript class ScrollingList extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { // 捕获更新前的一些信息 return this.listRef.current.scrollHeight; } componentDidUpdate(prevProps, prevState, snapshot) { // 使用snapshot保持滚动位置 const list = this.listRef.current; list.scrollTop += list.scrollHeight - snapshot; } } ``` 用于: - 在更新前捕获DOM信息 - 返回值传递给componentDidUpdate ### 5. componentDidUpdate() ```javascript class Example extends React.Component { componentDidUpdate(prevProps, prevState, snapshot) { // 比较props变化决定是否执行副作用 if (this.props.userID !== prevProps.userID) { this.fetchData(this.props.userID); } } } ``` 用于: - 对DOM进行操作 - 执行网络请求 - 注意要比较props或state以避免死循环 ## 卸载阶段 ### componentWillUnmount() ```javascript class Example extends React.Component { componentWillUnmount() { // 清理订阅和定时器 this.subscription.unsubscribe(); clearInterval(this.timer); } } ``` 用于: - 清理副作用 - 取消网络请求 - 清除定时器 - 取消订阅 ## 错误处理 ### 1. static getDerivedStateFromError() ```javascript class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { // 更新state使下一次渲染显示降级UI return { hasError: true }; } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } ``` ### 2. componentDidCatch() ```javascript class ErrorBoundary extends React.Component { componentDidCatch(error, errorInfo) { // 记录错误信息 logErrorToService(error, errorInfo); } } ``` ## 最佳实践 ### 1. 正确使用生命周期方法 ```javascript class BestPracticeExample extends React.Component { state = { data: null, error: null }; componentDidMount() { // 适合做初始化 this.fetchData(); } componentDidUpdate(prevProps) { // 根据props变化决定是否更新 if (this.props.id !== prevProps.id) { this.fetchData(); } } componentWillUnmount() { // 清理工作 this.isUnmounted = true; } fetchData = async () => { try { const response = await fetch(`api/data/${this.props.id}`); const data = await response.json(); if (!this.isUnmounted) { this.setState({ data }); } } catch (error) { if (!this.isUnmounted) { this.setState({ error }); } } }; render() { const { data, error } = this.state; if (error) { return <div>Error: {error.message}</div>; } if (!data) { return <div>Loading...</div>; } return <div>{/* 渲染数据 */}</div>; } } ``` ### 2. 避免常见错误 ```javascript class CommonMistakes extends React.Component { // 错误:在构造函数中调用setState constructor(props) { super(props); this.state = { count: 0 }; this.setState({ count: 1 }); // 错误 } // 错误:直接修改state wrongUpdate() { this.state.count = 1; // 错误 } // 正确:使用setState correctUpdate() { this.setState({ count: 1 }); } // 错误:在componentDidUpdate中无条件调用setState componentDidUpdate() { this.setState({ count: this.state.count + 1 }); // 错误,会导致死循环 } // 正确:在componentDidUpdate中有条件调用setState componentDidUpdate(prevProps) { if (this.props.count !== prevProps.count) { this.setState(state => ({ count: state.count + 1 })); } } } ``` ## 总结 类组件的生命周期方法提供了强大的功能: 1. 挂载阶段用于初始化和设置 2. 更新阶段用于响应变化和优化性能 3. 卸载阶段用于清理 4. 错误处理用于优雅降级 关键点: 1. 在正确的生命周期方法中执行相应的操作 2. 注意避免常见错误 3. 合理使用生命周期方法进行性能优化 4. 正确清理副作用以防止内存泄漏