React生命周期总结v16+和v16-

2023-10-18 20:36
文章标签 总结 react 生命周期 v16

本文主要是介绍React生命周期总结v16+和v16-,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

React的生命周期

生命周期就函数就是指在某一个时间刻会自动调用执行的函数,React生命周期分为三个阶段

挂载:组件被创建并插入真实dom
渲染(更新):组建的props或state发生变化时触发的组件更新
卸载:组件被从DOM中移除

生命周期有两个版本,react16.3版本引入了新版本生命周期的方法【new life cycle】,react16.3之前,react使用的都是旧版本的生命周期【old life cycle】

old life cycle

react生命周期

new life cycle

在这里插入图片描述

挂载(Mounting):

constructor

constructor 只会在组件初始化的时候触发一次
组件的构造函数,第一个被执行,若没有显式定义它,会有一个默认的构造函数,但是若显式定义了构造函数,我们必须在构造函数中执行
super(props),否则无法在构造函数中拿到this。如果不初始化 state 或不进行方法绑定,则不需要为 React
组件实现构造函数Constructor。 constructor中通常只做两件事:【初始化组件state,给事件处理方法绑定this】

constructor(props){// 要在构造函数中调用 setState,可以直接给 state 设置初始值super(props);this.state={count: 0,inputValue:"",},this.handleClick = this.handleClick.bind(this)}

getDerivedStateFromProps:

该函数会在组件化实例化后和重新渲染前调用(生成 VirtualDOM 之后,实际 DOM 挂载之前)
这是个静态方法,所以不能在这个函数里使用,this,有两个参数 props 和 state,分别指接收到的新参数和当前组件的 state对象,这个函数会返回一个对象用来更新当前的 ,state 对象,如果不需要更新可以返回 null。
无论是父组件的更新、props的变化或通过 setState 更新组件内部的 State,它都会被调用。
该生命周期函数必须有返回值,返回一个对象来更新 State,若返回 null 表明新 props 不更新 state。新的生命周期加了新特性,当组件实例化时,该方法替代了componentWillMount,而当接收新的 props 时,该方法替代了 componentWillReceiveProps 和componentWillUpdate。
适用于表单获取默认值。
static getDerivedStateFromProps(props, state)

import React, { Component } from 'react';  //(0)【引入组件第一种写法】
import '../App.css';class Homes extends Component {         //(0-1)对应第一种引入react引入方法类写法//(1)接下来两行为固定写法constructor(props) {// 要在构造函数中调用 setState,可以直接给 state 设置初始值super(props);this.state = {count: 0,inputValue: "",},this.handleClick = this.handleClick.bind(this)}handleClick = () => {this.setState({count: this.state.count + 1})}static getDerivedStateFromProps(props, state) {if (props.count !== state.count) {return {count: props.count}}return null}render() {return (<div><h1 onClick={this.handleClick}>Hello, world!{this.state.count}</h1></div>)}};
export default Homes;

现在可以显式传入 counter ,但是这里有个问题,如果想要通过点击实现 state.counter 的增加,但这时会发现值不会发生任何变化,一直保持 props 传进来的值。这是由于在 React 16.4^ 的版本中 setState 和 forceUpdate 也会触发这个生命周期,所以当组件内部 state 变化后,就会重新走这个方法,同时会把 state 值赋值为 props 的值。因此需要多加一个字段来记录之前的 props 值,这样就会解决上述问题。

import React, { Component } from 'react';  //(0)【引入组件第一种写法】
import '../App.css';
class Homes extends Component {         //(0-1)对应第一种引入react引入方法类写法//(1)接下来两行为固定写法constructor(props) {// 要在构造函数中调用 setState,可以直接给 state 设置初始值super(props);this.state = {count: 0,preCount:0,inputValue: "",},this.handleClick = this.handleClick.bind(this)}handleClick = () => {this.setState({count: this.state.count + 1})}static getDerivedStateFromProps(props, preCount) {if (props.count !== state.preCount) {return {count: props.count,preCount:props.counter}}return null}render() {return (<div><h1 onClick={this.handleClick}>Hello, world!{this.state.count}</h1></div>)}};
export default Homes;

render:

组件初始化,页面state或props发生变化时执行。 render是React 中最核心的方法,一个组件中必须要有这个方法,它会根据状态
state 和属性 props 渲染组件。这个函数只做一件事,就是返回需要渲染的内容,所以不要在这个函数内做其他业务逻辑,通常调用该方法会返回以下类型中一个:
       a.React元素这里包括原生的DOM 以及React 组件。
       b.数组和Fragment(片段):可以返回多个元素。
       c.Portals(插槽):可以将子元素渲染到不同的DOM中。
       d.字符串和数字:被渲染成DOM中的text节点。
       e.布尔值或者null:不渲染任何内容。

componentDidMount :

在组件挂载完成之后 (插入DOM树后) 立即调用。
componentDidMount()会在组件挂载后(插入 DOM 树中)立即调用。
该阶段通常执行依赖于DOM的操作,发送网络请求,添加订阅消息(会在componentWillUnmount取消订阅),添加事件监听,如果使用了Redux之类的数据管理工具也能触发action处理数据变化逻辑。此钩子函数中允许使用setState改变组件内的State。
注意:该生命周期函数在进行服务器端渲染时候不会触发(仅客户端有效)。如果在componentDidMount中调用setState,就会触发一次额外的渲染,多调用了一次render函数,由于他是在浏览器刷新屏幕前执行的,所以用户对此没有感知的,但是应当避免这样使用,这样带来的一定的性能问题,精良在constructor中初始化state对象。

class App extends React.Component  {constructor(props) {super(props)this.state = {count: 0}}componentDidMount () {this.setState({count: 1})}render ()  {return (<div className="count">counter值: { this.state.count }</div>)}
}

更新(Updation):

setState、useState、props变化、forceUpdate会触发组件的更新,但是组件是否从新渲染取决于shouldComponentUpdate。

shouldComponentUpdate:

函数会在组件更新之前,自动被执行。它要求返回一个布尔类型的结果,必须有返回值。返回true时组件更新,返回false则不更新。
当props或者state发生变化,在重新渲染执行之前,第一个是即将更新的props值,第二个是即将更新后的state值,可以根据更新前后的props或者state来比较加一些限制条件,决定是否更新进行性能优化,当该方法返回的布尔值false告知react无需重新渲染时,render,UNSAFE_componentWillUpdate和conponentDidUpdate等生命周期钩子函数都不会被触发。
    a.  此钩子函数在初始化渲染和使用forceUpdate方法的情况下不会被触发, 使用forceUpdate会强制更新
    b.  禁止在此函数中使用setState方法,会导致循环调用

shouldComponentUpdate(){console.log('shouldComponentUpdate---组件发生改变前执行')return true
}

现在就可以在控制台,console里看到结果了,并且结果是每次文本框发生改变时都会随着改变。如果你返回了
false,这组件就不会进行更新了。 简单点说,就是返回true,就同意组件更新;返回false,就反对组件更新。

getSnapshotBeforeUpdate (新):

保存状态快照。该生命周期函数会在组件即将挂载时触发,它的触发在 render 渲染函数之后。 这个方法在render之后,componentDidUpdate之前调用,有两个参数prevProps和prevState,标识更新之前的props和state,这个函数必须要和componentDidUpdate一起使用,并且要有一个返回值,默认是null,这个返回值座位第三个参数传递给componentDidUpdate。该生命周期函数执行完毕后就会立即触发componentDidUpdate 生命周期钩子。

getSnapshotBeforeUpdate(prevProps, prevState) {   console.log('#enter getSnapshotBeforeUpdate');   return 'foo';
}
componentDidUpdate(prevProps, prevState, snapshot) {   console.log('#enter componentDidUpdate snapshot = ', snapshot);
}

该生命周期函数能让你捕获某些从 DOM 中才能获取的(可能会变更的例如滚动位置),此生命周期返回的任何值都会作为第三个参数传递给 componentDidUpdate()。如不需要传递任何值,那么请返回 null。

componentDidUpdate:

在组件更新之后执行,它是组件更新的最后一个环。 该方法有三个参数【componentDidUpdate(prevProps,prevState, snapshot){}】
    a.  prevProps: 更新前的props
    b.  prevState: 更新前的state
    c.  snapshot: getSnapshotBeforeUpdate()生命周期的返回值
组件每次重新渲染后会触发 componentDidUpdate 但是只有在组件首次渲染(即初始化)时触发的是componentDidMount钩子函数,初始化渲染后componentDidMount 不会再被触发。 操作 DOM;发送网络请求。 在componentDidUpdate 生命周期函数中调用 setState 方法时,确实需要加上条件判断,以避免死循环的发生。通过判断 prevProps、prevState 和 this.state 之间的数据变化,来判断是否执行相关的 state 变更逻辑,这使得尽管在 componentDidUpdate 中调用了 setState 进行再更新,如果条件不成立state就不会进行更新,从而避免了死循环的发生。

	componentDidUpdate(prevProps){if (this.props.id !== prevProps.id){this.fetchData(this.props.id);}}

卸载(Unmounting):

componentWillUnmount:

它是在组件去除时执行。在组件卸载和销毁之前触发。可以利用这个生命周期方法进行事件的解绑。 用于移除事件监听器;取消网络请求;取消定时器;解绑DOM 事件。 在该方法中调用 setState 不会触发 render,因为所有的更新队列,更新状态都被重置为null。这个生命周期在一个组件被卸载和销毁之前被调用,因此不应该再这个方法中使用setState,因为组件一旦被卸载,就不会再装载,也就不会重新渲染。
新版本的生命周期就开始废弃了componentWillMount、componentWillReceiveProps、componentWillUpdate的三个钩子,并为这几个钩子提供了别名

  • UNSAFE_componentWillMount:当组件被渲染出来之前
  • UNSAFE_componentWillReceiveProps:当组件收到新的props之前
  • UNSAFE_componentWillUpdate:组件更新前

父子组件加载顺序

父子组件初次加载会在子组件挂挂载完成后继续父组件的挂载

  • Parent 组件: constructor()
  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: render()
  • Child 组件: constructor()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: render()
  • Child 组件: componentDidMount()
  • Parent 组件: componentDidMount()

当执行render子组件的时候,才会进入子组件的生命周期,子组件的周期结束后,再回到上级的周期。 改变子组件自身状态

Child 组件: getDerivedStateFromProps()

  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()

修改父组件传入给子组件的 props 当父组件修改传递的 props 值时,会触发父子组件的更新

Parent 组件: getDerivedStateFromProps()

  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()
  • Parent 组件: componentDidUpdate()

只修改父组件的值 当父组件的值被修改时,会触发父组件的 render() 方法重新渲染,并递归地 r-render 子组件。这个过程中,会依次触发所有子组件的生命周期方法:

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()
  • Parent 组件: componentDidUpdate()

所以不管父组件有没有把数据传递给子组件,只要父组件
setState,都会走一遍子组件的更新周期。而且子组件被动更新会比主动更新所执行的流程多出来一个
componentWillReceiveProps 方法。

子组件修改自身state

当我们修改子组件中的数据时,只有子组件会经历更新生命周期,而父组件不会。

  • 子组件 getDerivedStateFromProps
  • 子组件 shouldComponentUpdate
  • 子组件 render
  • 子组件 getSnapShotBeforeUpdate
  • 子组件 componentDidUpdate

卸载子组件,触发父组件的重新渲染、子组件销毁

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentWillUnmount()
  • Parent 组件: componentDidUpdate()

当子组件自身状态改变时,不会对父组件产生副作用的情况下,父组件不会进行更新,即不会触发父组件的生命周期,当父组件中状态发生变化(包括子组件的挂载以及卸载)时,会触发自身对应的生命周期以及子组件的更新。

完结~

这篇关于React生命周期总结v16+和v16-的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/234996

相关文章

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi

Java反转字符串的五种方法总结

《Java反转字符串的五种方法总结》:本文主要介绍五种在Java中反转字符串的方法,包括使用StringBuilder的reverse()方法、字符数组、自定义StringBuilder方法、直接... 目录前言方法一:使用StringBuilder的reverse()方法方法二:使用字符数组方法三:使用自

Python依赖库的几种离线安装方法总结

《Python依赖库的几种离线安装方法总结》:本文主要介绍如何在Python中使用pip工具进行依赖库的安装和管理,包括如何导出和导入依赖包列表、如何下载和安装单个或多个库包及其依赖,以及如何指定... 目录前言一、如何copy一个python环境二、如何下载一个包及其依赖并安装三、如何导出requirem

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Python中连接不同数据库的方法总结

《Python中连接不同数据库的方法总结》在数据驱动的现代应用开发中,Python凭借其丰富的库和强大的生态系统,成为连接各种数据库的理想编程语言,下面我们就来看看如何使用Python实现连接常用的几... 目录一、连接mysql数据库二、连接PostgreSQL数据库三、连接SQLite数据库四、连接Mo

Git提交代码详细流程及问题总结

《Git提交代码详细流程及问题总结》:本文主要介绍Git的三大分区,分别是工作区、暂存区和版本库,并详细描述了提交、推送、拉取代码和合并分支的流程,文中通过代码介绍的非常详解,需要的朋友可以参考下... 目录1.git 三大分区2.Git提交、推送、拉取代码、合并分支详细流程3.问题总结4.git push

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

Kubernetes常用命令大全近期总结

《Kubernetes常用命令大全近期总结》Kubernetes是用于大规模部署和管理这些容器的开源软件-在希腊语中,这个词还有“舵手”或“飞行员”的意思,使用Kubernetes(有时被称为“... 目录前言Kubernetes 的工作原理为什么要使用 Kubernetes?Kubernetes常用命令总

关于Maven生命周期相关命令演示

《关于Maven生命周期相关命令演示》Maven的生命周期分为Clean、Default和Site三个主要阶段,每个阶段包含多个关键步骤,如清理、编译、测试、打包等,通过执行相应的Maven命令,可以... 目录1. Maven 生命周期概述1.1 Clean Lifecycle1.2 Default Li