Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术随笔

    • git教程
    • 前端模块化:CommonJS,AMD,CMD,ES6
    • 如何动态加载本地图片
    • GitHub自动部署脚本
    • React生命周期详解
      • 前言
      • 生命周期函数的分类与作用
      • 1.挂载阶段
        • constructor
        • static getDerivedStateFromProps
        • componentDidMount
      • 2.更新阶段
        • static getDerivedStateFromProps
        • 🚨componentWillReceiveProps
        • shouldComponentUpdate
        • render
        • getSnapshotBeforeUpdate
        • componentDidUpdate
      • 3.卸载阶段
        • componentWillUnmount
      • 不常用的知识点
        • 1.state|props初始化
      • 图解生命周期
        • v16.4
        • v15
      • 参考资料
    • 将父组件的props作为组件的初始state的几种方案
    • webpack基础入门
    • StackOver记录:如何在function中使用redux
    • React中使用onClick时的三种性能优化
    • 思考React状态管理
    • forEach/for..in/of
    • styled-components使用记录
    • 深入理解forEach与forof
    • Node技术架构
    • Redux、Mobx状态管理杂谈
    • JS中的类型检测
    • 如何判断图片是否在可视区域
    • 如何使用图片的懒加载操作
    • JavaScript模块化:从CommonJS到AMD
    • git查看:修改用户名、密码
    • 保持数据Immutable的几种写法
    • 如何实现一个Promise.all
    • resolve(Promise对象)会多出两个微任务
    • todo_基于Mocha的测试驱动开发
    • 浏览器页面渲染机制
    • todo-响应式编程之数据劫持
    • todo-immer库的介绍
    • React-Hooks 基础原理解析
    • JS基本功
    • 函数闭包与this指针
    • 收集 DUMI 配置过程中遇到的问题
    • typescript 类型工具
    • 统一接口的导入导出
    • 网络安全:如何预防 XSS 攻击
    • 浏览器页面渲染机制【2023】
    • 跨域资源请求
    • 浏览器事件循环机制
    • 如何理解浏览器的 user agent 用户代理的含义?
  • 转载文章

  • Mac相关

  • 前端学习周报

  • 包管理工具

  • 技术随笔
  • 技术随笔
wangjiasheng
2021-12-04
目录

React生命周期详解

# 前言

目前React的类组件依旧是我日常开发构建组件的主要方式,尽管React-Hooks一直被认为是未来React发展趋势,了解Class组件内置的生命周期函数对后续过渡到Hooks时代也是有帮助的。

本篇博客需要记录的问题有:

  1. react 各个生命周期函数的用法。
  2. 新增的React16.4新增的函数以及用法。

# 生命周期函数的分类与作用

生命周期函数大致可以分为3类阶段:

  1. 挂载阶段
  2. 更新阶段
  3. 卸载阶段

下面开始分阶段介绍:

# 1.挂载阶段

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

  • constructor() 构造器

    这个阶段constructor函数只解决两件事:

    • 通过this.state赋值对象来初始化内部state。
    • 为事件处理函数绑定实例(ps:虽然这个要多写点代码,但是貌似性能不错)
  • static getDerivedStateFromProps()

    • 在初始化挂载及后续更新时都会被调用。
    • 返回一个对象来更新state
    • 应用:
      • 父组件渲染会导致子组件渲染,可以在此生命周期函数对数据进行拦截
  • render()

    • class 组件中唯一必须实现的方法
    • 支持返回的参数:
      • JSX语法
      • null or false
  • componentDidMount()

    • 会在组件实例挂载后(插入 DOM 树中)立即调用
    • 应用:
      • 可以在此生命周期发起网络请求。

# constructor

constructor(props) {
  super(props);
  // 不要在这里调用 this.setState()
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}

// 下面这中写法貌似也是可以的
// state 直接作为类组件的一个属性。
class App extends React.Component{
  state = { counter: 0} 
}
1
2
3
4
5
6
7
8
9
10
11
12
  • 如果没有写constructor函数,会有一个默认的构造函数,所以可以不显式定义

  • 如果要在constructor函数中使用this指针,一定需要super(props)

# static getDerivedStateFromProps

static getDerivedStateFromProps(nextProps, prevState,snapshot) {
  // 根据nextProps和prevState计算出预期的状态改变,返回结果会被送给setState
  // 注:这里无法使用 this 指针
}
1
2
3
4
  • 该函数是一个纯函数:纯函数的意思就是说输出完全决定于输入。

    (nextProps,prevState) →\rightarrow→ newState

  • 此函数用于替换掉大部分的render前的生命周期函数,包括:

    • componentWillReceiveProps

    • componentWillMount

      注:在此生命周期中发起AJAX请求是无法赶在首次render之前拿到数据结果的。

    • componentWillUpdate

    替换原因:Reactv17会采用Fiber,render函数之前的所有函数都有可能被执行多次。

# componentDidMount

可以在此阶段,使用AJAX请求数据

componentDidMount(){
    axios.post('https://web-api.juejin.im/v3/web/wbbr/bgeda')
        .then((res)=>{console.log('axios 获取数据成功:'+JSON.stringify(res))  })
        .catch((error)=>{console.log('axios 获取数据失败'+error)})
}
1
2
3
4
5

# 2.更新阶段

当组件实例被创建并插入 DOM 后时,其生命周期调用顺序如下:

  • static getDerivedStateFromProps()
    • 在初始化挂载及后续更新时都会被调用。
    • 返回一个对象来更新state
    • 应用:
      • 父组件渲染会导致子组件渲染,可以在此生命周期函数对数据进行拦截
  • shouldComponentUpdate
    • 在此生命周期,可以优化渲染性能。
    • 默认return true,可以 return false 停止渲染
  • render()
    • class 组件中唯一必须实现的方法
    • 支持返回的参数:
      • JSX语法
      • null or false
  • getSnapshotBeforUpdate()
    • 没啥用,可以处理视图层相关的操作。
  • componentDidUpdate()
    • 可以解决setState(,callbakc)

# static getDerivedStateFromProps

由于React更新后,render前的方案都需要被反复调用,所以无论在挂载阶段,还是在更新阶段,此函数都会执行。

使用方法见:点击跳转

# 🚨componentWillReceiveProps

非常常用的一个控制状态更新的生命周期函数,在旧版React这样的生命周期函数只有两个:

  1. shouldComponentUpdate:只能 return true 或者 false

  2. componentWillReceiveProps:

    • 通过比较两个props:nextProps(新)和this.props(旧,因为还没有render),可以直接对state状态进行更新,并且注意的是由于是在render函数之前,所以这种更新是同步的。

      state = {
        a: 0
      }
      componentWillReceiveProps(nextProps){
        this.setState({a:1})
        console.log(this.state.a) // 0
      } 
      
      render(){
      	console.log(this.state.a) // 1
      } 
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
    • 注:这样一来会破坏掉state数据的==单一数据源==的特性,导致组件状态变得不可测。

# shouldComponentUpdate

在React中,当prop或者state发生变化时,可以通过在shouldComponentUpdate生命周期函数中执行return false来阻止页面的更新,从而减少不必要的render执行。

shouldComponentUpdate(nextProps,nextState){
// 判断:this.props与nextProps | this.state与nextState
// 注:不要使用JSON.stringfy()进行深比较,非常影响效率、损耗性能。
  if(  条件判断  ){
    return false
  }
  return true
}
1
2
3
4
5
6
7
8

技巧:如果使用pureComponent会自动对状态进行判断

class App extends React.pureComponent{
  
}
1
2
3

# render

没啥好说的,

# getSnapshotBeforeUpdate

见componentDidUpdate():点击跳转

# componentDidUpdate

可以用于替换setState(,callback)函数,setState对状态修改后,会进入到componentDidUpdate这个生命周期函数。

state = {
  a: 0,
  b: 0
}
// 会刷新3次
this.setState({a:1},()=>{
  this.setState({b:1},()=>{
    this.setState({c:1})
  })
})

// 使用componentDidUpdate替换写法
// !如果在此生命周期中,使用this.setState()会引发循环渲染
// 所以必须有条件判断
componentDidUpdate(nextProps,nextState){
  if(nextState.a ===1){
    this.setState({b:1})
  }
  if(nexState.a ===1 && nextState.b===1){
    this.setState({c:1})
  }
}
// 可以发现这种写法很low,这个时候需要重新思考数据的设计模式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
点击查看

除此以外,getDerivedStateFromProps还可以与getSnapshotBeforeUpdate配合使用,后者的值可以作为getDerivedStateFromProps的第三个参数输入:

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // snapshot咋看是组件级别的某个“快照”,其实返回任何值
    // 官方推荐:在此阶段可以获取DOM元素,但是具体的有效实例没有发现
    // 程墨更是直接不推荐使用
    return 'foo';
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('#enter componentDidUpdate snapshot = ', snapshot);
  }
1
2
3
4
5
6
7
8
9
10

# 3.卸载阶段

卸载阶段只有一个生命周期函数,componentWillUnmount()会在组件卸载及销毁之前直接调用。

# componentWillUnmount

在此方法中执行必要的清理操作:

  • 清除 timer,取消网络请求或清除
  • 取消在 componentDidMount() 中创建的订阅等

注:不应该再这个方法中使用 setState,因为组件一旦被卸载,就不会再装载,也就不会重新渲染。

# 不常用的知识点

# 1.state|props初始化

  • state的初始化函数:constructor
  • props的初始化函数:defaultProps

这个牵扯到一个知识点,React声明类组件实际上有两种方式:

  1. ES5原生方式React.createClass定义的组件。

    var ShowTitle = React.createClass({
      getDefaultProps:function(){
        return{
          title : "React"
        }
      },
      getInitialState:function(){
        return {
          title : "React"
        }
      }
      render : function(){
        return <h1>{this.props.title}</h1>
      }
    });
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    🚨 目前这种写法已经不推荐了。

  2. ES6形式,通过继承React.component的方式定义的组件,也是目前React官方最为推荐的写法。

    class App extends React.Component {
      // defaultProps 作为静态属性
      static defaultProps = {
        title: "react"
      }
      constructor(props){
        super(props)
        this.state = {}
      }
    }
    
    // 别的教程中,对defaultProps配合 prop-types 使用
    App.defaultProps = {
      defaultValue : "Hello"
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

# 图解生命周期

# v16.4

React16.4生命周期

图片资源来源于React官网:https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

注:16.3 React 修复了getDerivedStateFromProps 在setState()不更新的Bug。

# v15

还有一张知乎程墨的图:主要就是props改变后多走了一步componentWillReceiveProps

# 参考资料

1.知乎程墨-React v16.3之后的组件生命周期函数 (opens new window)

2.React官网-生命周期 (opens new window)

编辑 (opens new window)
#React
上次更新: 2022/04/06, 15:04:00
GitHub自动部署脚本
将父组件的props作为组件的初始state的几种方案

← GitHub自动部署脚本 将父组件的props作为组件的初始state的几种方案→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式