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 组件的生命周期。

相关推荐
知道了啊3 小时前
react生命周期
javascript·react.js·ecmascript
烟雨国度5 小时前
双向数据绑定原理图
前端·javascript·vue.js
GISer_Jing5 小时前
React速成
前端·javascript·react.js
李元中5 小时前
2024下半年软考中级软件设计师,这100题,必做!
java·开发语言·javascript·人工智能·算法·ecmascript
软件测试雪儿6 小时前
外包干了5天,技术明显退步。。。。。
面试·软件测试面试
爱米的前端小笔记6 小时前
前端面试:项目细节重难点问题分享(18)
前端·经验分享·面试·职场和发展·求职招聘
GoppViper7 小时前
uniapp view怎么按长度排列一行最多四个元素,并且换行后,每一行之间都有间隔
前端·uni-app·uniapp·样式·样式控制
敏编程7 小时前
网页前端开发之Javascript入门篇(9/9):对象
开发语言·javascript
鱼跃鹰飞8 小时前
大厂面试真题-说说synchronized的锁升级过程
java·面试·职场和发展