x-note
  • Introduction
  • JavaScript
    • JavaScript 作用域链
    • JavaScript 数据结构与类型
    • JavaScript 原型
    • JavaScript this 关键字
    • JavaScript 函数
    • JavaScript delete 运算符
    • JavaScript 内存管理与垃圾回收
    • JavaScript 严格模式与混乱模式
    • JavaScript 数字精度丢失
    • JavaScript 并发模型
    • 利用原型链实现继承
  • ECMAScript
    • ECMAScript 6 变量及常量的声明
    • ECMAScript 6 变量的解构赋值
    • ECMAScript 6 Promise 对象
    • ECMAScript 6 Symbol
    • ECMAScript 6 Proxy
    • ECMAScript 6 Reflect
    • ECMAScript 6 new.target
    • ECMAScript 6 Set 和 WeakSet
    • ECMAScript 6 Map 和 WeakMap
    • ECMAScript 6 Iterator
    • ECMAScript 6 Generator
    • ECMAScript 6 class
    • ECMAScript 7
    • ECMAScript 8 async 函数
    • ECMAScript 8 内存共享与原子性
    • ECMAScript 8 Others
    • ECMAScript 2018
    • ECMAScript 2019
  • CSS
    • CSS 块格式化上下文(BFC)
    • CSS 盒模型
    • CSS 外边距合并
    • CSS Float
    • CSS Position
    • CSS Border-Image
    • CSS BEM
    • CSS 表布局详解
    • 页面布局之单列布局
    • 页面布局之多列布局
  • React
    • React 组件的生命周期
    • React 虚拟 DOM
    • React Reconciliation
    • React Diff 算法核心
    • React Fiber
    • React Scheduling
    • React Context API
    • React Refs
    • React HMR
    • React Hook
  • VUE
    • VUE 响应式系统
    • VUE 渲染机制
    • 关于 Vue 的思考
  • Webpack
    • Webpack 基本概念
    • Webpack HMR
  • Babel
    • @babel/preset-env
  • WEB
    • WEB 基础知识及概念
      • 屏幕测量单位
      • 重绘与重排
      • 前端模块化系统
      • WEB 客户端存储
      • 浏览器的渲染过程
    • WEB 性能优化
      • WEB 性能指标
      • WEB 图片优化
      • 懒加载资源
    • WEB 安全
      • XSS
      • XSRF
      • 点击劫持
      • 同源策略(Same Origin Policy,SOP)
    • WEB 解决方案
      • webp 兼容方案
      • WEB 拖拽实现方案
    • WEB SEO
  • Git
    • Git 工作流
    • Git 内部原理
  • 传输协议
    • UDP
      • UDP 基本概念
    • TCP
      • TCP 基本概念
    • HTTP
      • HTTP 基础
      • HTTP 缓存
      • HTTP-2
      • HTTP-3
      • HTTPS
      • 自定义 HTTPS 证书
  • Protocol Buffers
    • Protocol Buffers 基础
  • gRPC
    • gRPC 简介
    • gRPC 基础概念
    • GRPC with GraphQL and TypeScript
  • 正则表达式
    • 正则表达式基础
    • 正则表达式的悲观回溯
  • 基础算法
    • 冒泡排序
    • 插入排序
    • 选择排序
    • 快速排序
    • 归并排序
    • 希尔排序
    • 堆排序
    • 桶排序
    • 计数排序
    • 基数排序
    • 二叉树的遍历
    • 动态规划
    • 回溯
  • 压缩算法
    • HPACK
    • QPACK
  • 设计模式
    • DDD
      • 模型元素的模式
    • 常见设计模式
      • 工厂方法
      • 抽象工厂
      • 构造器
      • 原型
      • 单例模式
      • 适配器模式
      • 桥接模式
      • 组合模式
      • 外观模式
      • 享元模式
      • 代理模式
      • 责任链模式
      • 命令模式
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 观察者模式
      • 状态模式
      • 策略模式
      • 模版方法模式
      • 访问者模式
      • 依赖注入
    • MVC
    • MVP
    • MVVM
  • 颜色空间
    • LCH
由 GitBook 提供支持
在本页
  • 三个阶段与相关 API
  • 挂载
  • 更新
  • 卸载
  • API 详情
在GitHub上编辑
  1. React

React 组件的生命周期

上一页React下一页React 虚拟 DOM

最后更新于7年前

每一个 React 组件的实例都拥有着一套完善的生命周期,主要分为挂载、更新和卸载三个大阶段,每一个阶段都拥有着更为细化的生命周期。

三个阶段与相关 API

挂载

挂载阶段相关的生命周期 API:

  1. static getDefaultProps

  2. initialize state

  3. constructor(props)

  4. static getDerivedStateFromProps(nextProps, prevState)(V 16.3.0)

  5. componentWillMount() / UNSAFE_componentWillMount()

  6. render()

  7. componentDidMount()

更新

更新阶段相关的生命周期 API:

  1. componentWillReceiveProps(nextProps) / UNSAFE_componentWillreceiveProps(nextProps)

  2. static getDerivedStateFromProps(nextProps, prevState)(V 16.3.0)

  3. shouldComponentUpdate(nextProps, nextState)

  4. componentWillUpdate(nextProps, nextState) / UNSAFE_componentWillUpdate(nextProps, nextState)

  5. render()

  6. getSnapshotBeforeUpdate(prevProps, prevState)(V 16.3.0)

  7. componentDidUpdate(prevProps, prevState, snapshot)

卸载

卸载阶段相关的生命周期 API:

  1. componentWillUnmount()

API 详情

static getDefaultProps

定义默认属性

class MyComponent extends React.Component {
    static getDefaultProps = {}
    // ...
}

initialize state

初始化 state。

当前版本的官方文档(V 16.3.0)未说明该阶段。在 React V 16.0.0 之前,React.createClass 仍未废弃的情况下,还包含着这个阶段相关的 api。当前的官方文档中的示例,初始化state都是在constructor中完成。但是文档中说到_(The constructor is the right place to initialize state. _To do so, just assign an object to _this.state),_猜测实际上仍存在该阶段

class MyComponent extends React.Component {
    // ES7 语法实现初始化 state
    state = {}
    // ...
}

constructor(props)

构造器函数,在此阶段进行初始化 state 和事件处理器(event handler)的上下文绑定

  • React.Component的子类的构造器函数里,一定得调用super(props),否则this.props将会是undefined

  • 不要在这个阶段调用this.setState(),倘若要改变 state,只需要 state 对象进行 assign 操作即可

  • 如果,不需要初始化 state 也不打算给 class 实例绑定,事件处理器,就没有必要实现 conostructor

  • 在此阶段改变 state 时,不处理受到 props 影响的值,而是在componentWillMount或getDerivedStateFrom内处理

class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
        this.btnClickHandler = this.btnClickHandler.bind(this);
    }
    btnClickHandler (e) {}
    // ...
}

static getDerivedStateFromProps(nextProps, prevState)

React v16.3.0新增 API。getDerivedStateFromProps()在组件初始化和接收新的 props 时调用。将会返回一个 object 去更新 state,或是返回一个null表示新的 props 不会导致 state 更新。

  • 无论 props 是否改变,该函数都会被调用

  • 通常情况下,this.setState()不会触发该函数

  • 一旦使用了这个新的生命周期函数,不安全的生命周期函数将不会被调用

class MyComponent extends React.Component {
    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProp.value !== prevState.selectedVal) {
            return {
                selectedVal: nextProps.value,
            }
        }
        return null;
    }
    // ...
}

UNSAFE_componentWillMount()

componentWillMount() 的别名。在即将挂载的时候调用。由于该阶段在render之前,因此,在该阶段异步的调用setState()不会触发额外的渲染。在挂载之前,最后一次允许改变 state 的阶段。

  • 该生命周期函数会受到static getDerivedStateFromProps()和getSnapshotBeforeUpdate()的影响而无法使用

class MyComponent extends React.Component {
    UNSAFE_componentWillMount() {
        if (this.props.mod === 'mod1') {
            this.setState({
                mod1State
            });
        }
    }
    // ...
}

componentDidMount()

componentDidMount()在挂载完成后调用。在该阶段可进行加载远程数据,订阅事件,设置定时器等操作。

该阶段调用 setState() 会触发额外的渲染,处理不当可能会导致死循环

class MyComponent extends React.Component {
    _loadData() { // ... }
    componentDidMount() {
        this._loadData();
        this.autoLoadDataIntevalKey = setInterval(this._loadData, 30 * 1000);
        this.subscriptKey = subscriptNoticeMsg((msg) => {
            alert(msg);
        });
    }
    // ...
}

UNSAFE_componentWillReceiveProps(nextProps)

componentWillReceiveProps()的新名称,在一个已经挂载的组件接收到新 props 时被调用。如果需要在此阶段根据 props 更新 state,最后先比较 this.props和nextProps后再调用setState()

  • 如果是父组件导致重新渲染,即使 props 没变更也会被调用

  • componentWillReceiveProps计划在 React V17.0.0 之后废弃掉

  • 该生命周期函数会受到static getDerivedStateFromProps()和getSnapshotBeforeUpdate()的影响而无法使用

class MyComponent extends React.Component {
    componentWillReceiveProps(nextProps) {
        if (nextProps.value === this.props.value) {
            this.setState({
                selectedVal: nextProps.value,
            });
        }
    }
    // ...
}

shouldComponentUpdate(nextProps, nextState)

shouldComponentUpdate()在一个已经挂载的组件接收到新的 props 或 state 时被调用,其返回一个布尔值告诉 React 是否应该进行更新。默认情况下,每一次的状态变更都会进行重新渲染。

当shouldComponentUpdate()的返回false时,UNSAFE_componentWillUpdate(),render()和componentDidUpdate()都不会被调用。

对于React.PureComponent的子类,shouldComponentUpdate()对 props 和 state 进行了一次浅比较。

如果,React.PureComponent的子类重写了shouldComponentUpdate() React 在开发环境下会有以下警告:

Warning: XXXX has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.

class MyComponent extends React.Component {
    shouldComponentUpdate(nextProps, nextState) {
        for (let key in nextProps) {
            if (nextProps[key] === this.props[key]) {
                return true;
            }
        }
        for (let key in nextState) {
            if (nextState[key] === this.state[key]) {
                return true;
            }
        }
    }
    // ...
}

UNSAFE_componentWillUpdate(nextProps, nextState)

componentWillUpdate()的新名称,在一个已经挂载的组件接收到新的 props 或 state,并且shouldComponentUpdate()返回true时被调用。这是在更新之前最后一次准备的机会。

  • 不要在这个阶段调用this.setState(),dispatch Redux 的 action 也一样,否则,可能会导致 React 组件在UNSAFE_componentWillUpdate()返回前就进行了一次更新。

  • componentWillUpdate计划在 React V17.0.0 之后废弃掉

  • 该生命周期函数会受到static getDerivedStateFromProps()和getSnapshotBeforeUpdate()的影响而无法使用

getSnapshotBeforeUpdate(prevProps, prevState)

React V16.3.0 新增的生命周期。在当前已挂载的组件调用 render() 之后调用。该函数的返回值将作为componentDidMount()的第三个参数传递下去。

一旦使用了这个新的生命周期函数,不安全的生命周期函数将不会被调用

class ScrollingList extends React.Component {
  listRef = React.createRef();

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the current height of the list so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      return this.listRef.current.scrollHeight;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    if (snapshot !== null) {
      this.listRef.current.scrollTop +=
        this.listRef.current.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

componentDidUpdate(prevProps, prevState, snapshot)

componentDidUpdate()在更新结束后立刻被调用,可以在这个阶段进行 DOM 的操作、网络请求等。

class MyComponent extends React.Component {
  _loadData() {}
  componentDidUpdate(prevProps, prevState, snapshot) {
    if (prevProps.province !== this.props.province) {
      this._loadData();
      this.amap.setProvince(this.props.province)
    }
  }
  // ...
}

componentWillUnmount()

当一个组件即将被卸载和销毁时会立刻调用componentWillUnmount()函数,在这个阶段可以进行取消网络、清空订阅等操作。

class MyComponent extends React.Component {
  componentWillUnmount() {
    clearInterval(this.intervalKey);
    unsubscript(this.subscriptKey);
  }
  // ...
}

componentWillMount 这个名称计划在 React V17.0.0 之后废弃掉。react 提供了 这个工具去自动更新

rename-unsafe-lifecycles codemod