React生命周期

React 生命周期分为 mountupdateunmount 三个阶段。每个阶段对应两个生命周期(unmount 除外)。在 update 阶段还存在两个特殊的周期 shouldcomponentUpdatecomponentWillReceiveProps

React 生命周期

生命周期方法

React v16.3.0 之前

1. componentWillMount()

  • 调用时期
    • render() 方法之前
  • 说明
    1. 在组件挂载之前调用且全局只调用一次。
    2. componentWillMount() 是在 render() 之前执行,所以在这里使用 setState() 不会触发 render()

2. render()

  • 调用时期
    • componentWillMount() 之后
    • componentWillReceiveProps() 之后
    • componentWillUpdate() 之后
  • 说明
    1. render() 是必不可少的生命周期,用于渲染 DOM
    2. 不能在 render() 里修改 state,修改 state 会引起 render()render() 里又会再次修改 state… 造成死循环。

3. componentDidMount()

  • 调用时期
    • 组件挂载完成之后调用,且全局只调用一次
  • 说明
    1. 此时完成真实 DOM 元素插入,可以获取到真实 DOM 元素及 refs
    2. 此时可以修改 state 触发 render()
    3. 此时进行异步数据请求,可以保证在更新状态时组件挂载完成

4. componentWillReceiveProps(nextProps)

  • 调用时期
    • 已经挂载的组件接收到新的 props
    • 父组件重新渲染时
  • 说明
    1. 该生命周期的触发时间为 props 即将变化前
    2. 在该钩子内可以通过参数 nextProps 获取变化后的 props 参数,通过 this.props 访问之前的 props
    3. 如果需要在 props 发生变化时更新 state,需要比较 this.statenextProps,然后使用 setState 来更新 state

5. shouldComponentUpdate(nextProps, nextState)

  • 调用时期
    • 组件挂载之后,每次 stateprops 发生变化时调用 shouldComponentUpdate判断是否需要重新渲染组件。
  • 说明
    1. 默认返回 true,需要重新render。返回false则不触发渲染
    2. 有一个例外,如果开发者调用this.forceUpdate强制更新,React组件会无视这个钩子
    3. 需要优化的情况 详情
    4. 如果 shouldComponentUpdate(nextProps, nextState) 返回 false,那么 componentWillUpdate(nextProps, nextState)render()componentDidUpdate() 都不会被触发

6. componentWillUpdate(nextProps, nextState)

  • 调用时期
    • shouldComponentUpdate() 生命周期钩子返回 true,或者调用 this.forceUpdate() 之后
  • 说明
    1. componentWillUpdate() 在每次更新前都会调用,在这里调用 setState(),可能会陷入死循环
    2. 如果 shouldComponentUpdate() 返回了 false,那么不会触发

7. componentDidUpdate(prevProps, prevState, snapshot)

  • 调用时期
    • 组件更新之后,在 componentWillUpdate()render() 之后
  • 说明
    1. 同样,在每次更新之后都会调用,所以使用 setState() 可能会陷入死循环,需要自行判断
    2. componentDidMount() 类似,可以在这里操作 DOM 和 发起网络请求
    3. 如果 shouldComponentUpdate() 返回了 false,那么不会触发
    4. 搭配 getSnapshotBeforeUpdate 生命周期钩子使用的时候,第三个参数是 getSnapshotBeforeUpdate 的返回值。

8. componentWillUnmount()

  • 调用时期
    • 组件被卸载的时候调用
  • 说明
    1. 一般在 componentDidMount() 里面注册的事件需要在这里删除,如:
      document.addEventListener('click', () => {});
      
    2. 处理一些必要的清理操作,比如无效的 timerinterval,或者取消网络请求,或者清理任何在 componentDidMount() 中创建的 DOM 元素

三个带 will 的生命周期官方已不再推荐

  • componentWillMount()
  • componentWillReceiveProps(nextProps)
  • componentWillUpdate(nextProps, nextState)

React v16.3.0 新增生命周期

1. static getDerivedStateFromProps(props, state)

  • 调用时期
    • 初始化和更新阶段
  • 说明
    1. 根据父组件传来的 props 按需更新自己的 state
    2. 返回一个对象,就是要更新的 state 项(只会覆盖同名属性,不会全部重写),如果是 null 则不更新

2. getSnapshotBeforeUpdate(prevProps, prevState)

  • 调用时期
    • 组件即将挂载时调用,甚至比 render
  • 说明
    1. getSnapshotBeforeUpdate 生命周期钩子返回的值会被 componentDidUpdate 的第三个参数接收,我们可以利用这个通道保存一些不需要持久化的状态,用完即可舍弃。

3. componentDidCatch(error, info)

  • 调用时期
    • 捕获到错误
  • 说明
    1. 定制一个只有 componentDidCatch 生命周期钩子的 ErrorBoundary 组件,它只做一件事:如果捕获到错误,则显示错误提示,如果没有捕获到错误,则显示子组件。 详情

生命周期

前面提到,生命周期总结起来只有三个过程:

  • 挂载
  • 更新
  • 卸载

挂载和卸载只执行一次,更新则执行多次。

一个完整的生命周期会以此调用如下钩子

  • 挂载

    • constructor
    • componentWillMount
    • render
    • componentDidMount
  • 更新

    • componentWillReceiveProps(组件传入新的 props 或父组件重新渲染时才触发)
    • shouldComponentUpdate
    • componentWillUpdate
    • render
    • componentDidUpdate

参考: