React生命周期案例详解

React 组件的生命周期是指组件从创建、渲染、更新到卸载的整个过程。在 React 16 及之前的版本中,生命周期方法被分为几个不同的阶段:挂载(Mounting)、更新(Updating)、卸载(Unmounting)以及错误处理(Error Handling,React 16 引入)。但从 React 17 开始,一些生命周期方法被标记为不推荐使用(如 componentWillMount、componentWillReceiveProps、componentWillUpdate),并引入了新的钩子函数 getDerivedStateFromProps 和 componentDidMount(实际上 componentDidMount 在更早的版本就已存在,但这里强调其作为替代某些旧生命周期方法的作用)。在 React 18 中,又引入了新的并发特性,这可能会进一步影响生命周期的概念,但本文主要基于 React 16.x 和 17.x 进行讲解。

挂载(Mounting)

这是组件被插入到 DOM 中的过程。

constructor(props)

类组件的构造函数,初始化 state 或绑定事件处理函数时调用。

jsx

class MyComponent extends React.Component {

constructor(props) {

super(props);

this.state = {

count: 0

};

}

}

static getDerivedStateFromProps(props, state)

当组件实例化后和接收新的 props 时将被调用。它应返回一个对象来更新 state,或者返回 null 来表明新的 props 不需要更新任何 state。

jsx

class MyComponent extends React.Component {

static getDerivedStateFromProps(props, state) {

if (props.count !== state.count) {

return { count: props.count };

}

return null;

}

}

render()

必须的方法,当组件需要更新时被调用,返回组件要渲染的内容。

jsx

class MyComponent extends React.Component {

render() {

return <div>{this.state.count}</div>;

}

}

componentDidMount()

组件挂载到 DOM 之后调用。此时可以进行 API 调用、订阅等操作。

jsx

class MyComponent extends React.Component {

componentDidMount() {

// 执行 API 调用等

}

}

更新(Updating)

组件的 props 或 state 发生变化时会进入更新过程。

static getDerivedStateFromProps(props, state)

组件更新时被调用,用于根据新的 props 来设置 state。

shouldComponentUpdate(nextProps, nextState)

决定组件是否应该更新。默认返回 true。返回 false 会阻止更新。

jsx

class MyComponent extends React.Component {

shouldComponentUpdate(nextProps, nextState) {

if (nextProps.count === this.props.count) {

return false;

}

return true;

}

}

render()

更新后,重新渲染组件。

getSnapshotBeforeUpdate(prevProps, prevState)

真实的 DOM 更新前调用。返回的值作为 componentDidUpdate 的第三个参数。

jsx

class MyComponent extends React.Component {

getSnapshotBeforeUpdate(prevProps, prevState) {

// 例如,记录滚动位置等

return null;

}

}

componentDidUpdate(prevProps, prevState, snapshot)

更新后立即调用。可以在这执行 DOM 操作或者执行更多的更新操作。

jsx

class MyComponent extends React.Component {

componentDidUpdate(prevProps, prevState, snapshot) {

// 例如,处理 DOM 更新后的逻辑

}

}

卸载(Unmounting)

componentWillUnmount()

组件卸载和销毁之前调用。用于执行必要的清理操作,如取消网络请求、移除订阅等。

jsx

class MyComponent extends React.Component {

componentWillUnmount() {

// 清理操作

}

}

错误处理(Error Handling)

React 16 引入了错误边界的概念,可用以下生命周期方法捕获子组件树的 JavaScript 错误。

static getDerivedStateFromError(error)

当子组件树中有组件抛出错误后,这个生命周期方法会被调用,返回值将作为 state。

componentDidCatch(error, info)

该生命周期方法会在后代组件抛出错误后被调用,可以用来记录错误信息。

错误边界组件示例:

jsx

class ErrorBoundary extends React.Component {

constructor(props) {

super(props);

this.state = { hasError: false };

}

static getDerivedStateFromError(error) {

return { hasError: true };

}

componentDidCatch(error, info) {

// 可以将错误日志上报给你的服务器

console.log(error, info);

}

render() {

if (this.state.hasError) {

return <h1>Something went wrong.</h1>;

}

return this.props.children;

}

}

使用错误边界:

jsx

<ErrorBoundary>

<MyComponent />

</ErrorBoundary>

使用函数组件和 Hooks

在函数组件中,你可以使用 React Hooks 来模拟类组件中的生命周期方法。

useEffect 可以模拟 componentDidMount、componentDidUpdate 和 componentWillUnmount。

useState 和 useReducer 可以初始化 state,类似于 constructor。

useMemo 和 useCallback 可以优化性能,类似于 shouldComponentUpdate 的某些用例。

示例:

jsx

import React, { useState, useEffect } from 'react';

function MyComponent() {

const [count, setCount] = useState(0);

useEffect(() => {

// 类似于 componentDidMount 和 componentDidUpdate

document.title = `You clicked ${count} times`;

// 类似于 componentWillUnmount

return () => {

// 清理操作

};

}, [count]); // 依赖项数组,类似于 shouldComponentUpdate

return (

<div>

<p>You clicked {count} times</p>

<button onClick={() => setCount(count + 1)}>

Click me

</button>

</div>

);

}

以上是 React 生命周期的详细解释以及各个阶段对应的代码示例。希望这能帮助你更好地理解 React 组件的生命周期。

相关推荐
广药门徒6 分钟前
OpenMV IDE 的图像接收缓冲区原理
前端·人工智能·python
霸王蟹9 分钟前
常见面试题:Webpack的构建流程简单说一下。
前端·笔记·学习·webpack·node.js·vue
黄暄14 分钟前
Linux项目部署全攻略:从环境搭建到前后端部署实战
java·linux·运维·服务器·前端·后端·持续部署
island131439 分钟前
JAVA Web 期末速成
java·开发语言·前端
独行soc1 小时前
2025年渗透测试面试题总结-安恒[实习]安全服务工程师(题目+回答)
linux·数据库·安全·web安全·面试·职场和发展·渗透测试
小峰编程1 小时前
Python函数——万字详解
linux·运维·服务器·开发语言·前端·网络·python
海盐泡泡龟2 小时前
Javascript本地存储的方式有哪些?区别及应用场景?(含Deep Seek讲解)
开发语言·javascript·ecmascript
11054654012 小时前
23、电网数据管理与智能分析 - 负载预测模拟 - /能源管理组件/grid-data-smart-analysis
前端·能源
开发者小天2 小时前
React中startTransition的使用
前端·react.js·c#
@PHARAOH3 小时前
WHAT - 缓存命中 Cache Hit 和缓存未命中 Cache Miss
前端·缓存