React生命周期原理与用法踩坑笔记

yizhihongxing

React生命周期原理与用法踩坑笔记

React 是一个非常流行的前端框架,它有很多特色的 features,其中一项便是组件的生命周期。通过了解 React 组件的生命周期,可以更好的利用它提供的钩子函数,从而实现自己的需求。同时,在使用 React 开发中,我们也很容易遇到一些坑,接下来我们将从生命周期的原理以及踩坑经验两个方面,来分享 React 生命周期的攻略。

React 生命周期

基础概念

React 组件生命周期指的是从组件创建到销毁的整个过程,包括以下三个阶段:

  1. 挂载阶段(mounting):组件在创建时被挂载到 DOM 中;
  2. 更新阶段(updating):当组件的 props 或 state 发生改变时,会重新渲染并更新组件;
  3. 卸载阶段(unmounting):组件被从 DOM 中删除。

在这三个过程中,React 提供了一些钩子函数,可以帮助我们更好的控制组件的行为。下面是常见的钩子函数:

常见钩子函数

挂载阶段

  • constructor(props):初始化 state 和绑定方法,props 和 state 都可以在 constructor 中访问。
  • static getDerivedStateFromProps(props, state):从 props 中派生 state,返回值将会更新 state。
  • render():返回 React 元素来构建虚拟 DOM 树。
  • componentDidMount():组件已经被渲染到 DOM 中,在这个时刻可以进行一些异步操作、设置定时器等。

更新阶段

  • static getDerivedStateFromProps(props, state):和挂载阶段一样,用于从 props 中派生 state。
  • shouldComponentUpdate(nextProps, nextState):决定是否需要重新渲染组件,返回一个 bool 值。
  • render():同挂载阶段。
  • getSnapshotBeforeUpdate(prevProps, prevState):在 render 之后、更新 DOM 之前调用,用于获取新的状态或 props,通常用于滚动位置的保存。
  • componentDidUpdate(prevProps, prevState, snapshot):在更新后被调用,可以进行 DOM 操作。

卸载阶段

  • componentWillUnmount():组件被卸载时调用,可以进行一些清理工作(如计时器的清除、取消订阅等)。

示例说明

示例1:fetch 数据

在 componentDidMount 中请求后端 API 数据,更新 state,通过 props 向子组件传递数据以进行渲染。代码如下:

import React, { Component } from 'react';
import ChildComponent from './ChildComponent';

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { data: [] };
  }

  async componentDidMount() {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos');
    const data = await response.json();
    this.setState({ data });
  }

  render() {
    return (
      <ChildComponent data={this.state.data} />
    );
  }
}

export default ParentComponent;

示例2:滚动位置的保存

通过 getSnapshotBeforeUpdate 获取列表容器的 scrollTop 属性,再通过 componentDidUpdate 将列表容器的滚动位置保持到列表更新后的下次渲染中。代码如下:

import React, { Component } from 'react';
import ListItem from './ListItem';

class List extends Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
    this.state = { data: [] };
    this.intervalId = null;
  }

  componentDidMount() {
    this.intervalId = setInterval(() => {
      const data = this.state.data.slice();
      data.push(Math.random());
      this.setState({ data });
    }, 1000);
  }

  getSnapshotBeforeUpdate() {
    const listRef = this.listRef.current;
    return listRef.scrollHeight - listRef.scrollTop;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot !== null) {
      const listRef = this.listRef.current;
      listRef.scrollTop = listRef.scrollHeight - snapshot;
    }
  }

  componentWillUnmount() {
    clearInterval(this.intervalId);
  }

  render() {
    return (
      <div ref={this.listRef}>
        {this.state.data.map(item => (
          <ListItem key={item} item={item} />
        ))}
      </div>
    );
  }
}

export default List;

踩坑经验

在使用 React 过程中,我们也很容易碰到一些坑,接下来我们分享一些踩坑经验。

坑1:使用箭头函数

在声明函数时,使用箭头函数可以避免 this 问题的出现。当使用使用普通函数时, this 指向的是组件本身而非组件的实例。当从组件传递 function 系的 props 至子组件时,如果是普通函数就需要进行 bind 操作,而使用箭头函数则会自动绑定 this,避免了这个问题。示例代码如下:

class MyComponent extends Component {
  handleClick() {
    console.log(this); // undefined
  }

  render() {
    return (
      <button onClick={this.handleClick}>Click me!</button>
    );
  }
}

class App extends Component {
  handleClick() {
    console.log(this); // App component
  }

  render() {
    return (
      <MyComponent handleClick={() => this.handleClick()} />
    );
  }
}

坑2:避免在 shouldComponentUpdate 中使用 setState

在 shouldComponentUpdate 中进行 setState 操作会导致无限循环更新组件。在 shouldComponentUpdate 中应该避免使用 setState 来修改 state,因为 shouldComponentUpdate 中的 setState 不会再次调用 render 函数,而是直接进入 componentDidUpdate 导致死循环。如果需要在 shouldComponentUpdate 中修改 state,则需要使用 this.state 或 nextProps 进行计算。示例代码如下:

shouldComponentUpdate(nextProps, nextState) {
  if (nextProps.value === this.props.value && nextState.data === this.state.data) {
    return false;
  }
  return true;
}

总结

本篇分享了 React 生命周期的原理和用法,并提供了两个示例代码演示了生命周期的应用。同时也分享了两个常见的踩坑经验,希望阅读者可以在开发中更加高效地使用 React。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:React生命周期原理与用法踩坑笔记 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Win10更新四月正式版17134.166累积更新补丁 附更新内容和下载地址

    Win10更新四月正式版17134.166累积更新补丁攻略 本攻略将详细讲解Win10更新四月正式版17134.166累积更新补丁的安装过程,并提供更新内容和下载地址。请按照以下步骤进行操作: 步骤一:检查系统版本 首先,确保你的系统版本是Win10更新四月正式版17134.166。你可以通过以下步骤检查: 打开“设置”应用程序。 点击“系统”。 在左侧导航…

    other 2023年8月4日
    00
  • 如何修改vant的less样式变量

    如何修改vant的less样式变量 1. 简介 vant是一套基于Vue.js的移动端组件库,它采用了less作为样式预处理语言。通过修改vant的less样式变量,我们可以定制化组件的样式,以满足项目需求。 2. 修改vant的less样式变量的步骤 步骤一:安装vant 首先,我们需要在项目中安装vant。 npm install vant -S 步骤二…

    other 2023年6月28日
    00
  • 深入探究Java原型模式的魅力

    深入探究Java原型模式的魅力 什么是原型模式? 原型模式是一种通过克隆来创建对象的设计模式。在使用原型模式时,需要先创建一个原型对象,然后通过复制该原型对象来创建新的对象。这种方式可以避免重复创建相似的对象,可以提高程序的性能和可维护性。 原型模式的使用场景 原型模式适用于以下场景: 需要创建对象的时间和代价比较大,例如创建数据库连接或者网络连接; 需要在…

    other 2023年6月27日
    00
  • thinkPHP5框架实现基于ajax的分页功能示例

    ThinkPHP5框架实现基于ajax的分页功能示例攻略 1. 示例概述 本示例旨在演示如何使用ThinkPHP5框架实现基于ajax的分页功能。通过ajax异步加载数据和更新页面,实现数据分页展示的效果。整个示例包含以下几个步骤: 创建数据库和表 创建控制器和模型 创建视图文件 编写ajax请求和数据处理逻辑 更新视图展示 接下来,我们将详细介绍每个步骤以…

    other 2023年6月28日
    00
  • JavaScript定义变量和变量优先级问题探讨

    JavaScript定义变量和变量优先级问题探讨 JavaScript是一门变量类型松散的语言,它的变量定义和赋值方式有多种,也存在着一些变量优先级的问题。在本篇攻略中,我们将深入探讨JavaScript变量的定义和优先级问题,帮助你更好地理解和运用JavaScript。 变量定义 var 在JavaScript中,最常见的变量定义方式是使用var关键词。使…

    other 2023年6月27日
    00
  • (转)使用scp命令在linux操作系统之间传递文件

    (转)使用scp命令在linux操作系统之间传递文件 如果你需要在两台 Linux 主机之间进行文件传输,那么你可以使用 scp 命令。scp 程序将文件以加密的方式传输,确保数据的安全性。 步骤 使用以下命令将本地文件传输到远程主机: scp /path/to/local/file username@remote:/path/to/remote/ 在这个命…

    其他 2023年3月28日
    00
  • 详解spring applicationContext.xml 配置文件

    下面是“详解Spring applicationContext.xml配置文件”的完整攻略: 什么是Spring的applicationContext.xml配置文件? Spring的applicationContext.xml配置文件是Spring框架中用于配置应用程序上下文的核心配置文件。它可以包含所有bean的声明,以及它们之间的依赖关系等信息。 应用…

    other 2023年6月25日
    00
  • 利用SQL Server触发器实现表的历史修改痕迹记录

    以下是利用SQL Server触发器实现表的历史修改痕迹记录的完整攻略: 步骤1:创建历史记录表 首先,创建一个用于存储历史修改痕迹的表。假设我们有一个名为OrderHistory的表,包含以下字段:order_id、modified_date、modified_by和modification_details。 CREATE TABLE OrderHisto…

    other 2023年10月17日
    00
合作推广
合作推广
分享本页
返回顶部