浅谈React16组件的生命周期

React在16版本的时候对组件的生命周期函数作出了一些修改,这里我们简单来了解一下新的生命周期函数。

组件生命周期概述

1、初始化

在组件初始化阶段会执行

  1. constructor
  2. static getDerivedStateFromProps()
  3. render()
  4. componentDidMount()

componentWillMount() / UNSAFE_componentWillMount() 函数可能会被废弃,所以尽量避免在新的代码中使用

2.更新阶段

props或state的改变可能会引起组件的更新,组件重新渲染的过程中会调用以下方法:

  1. static getDerivedStateFromProps()
  2. shouldComponentUpdate()
  3. render()
  4. getSnapshotBeforeUpdate()
  5. componentDidUpdate()

componentWillReceiveProps() / UNSAFE_componentWillReceiveProps() 和componentWillUpdate() / UNSAFE_componentWillUpdate() 可能会被废弃所以尽量避免在新的代码中使用

3.卸载阶段

1.componentWillUnmount()

4.错误处理

1.componentDidCatch()

以上生命周期我们可以通过下图更加直观的查看

react 生命周期图

由于其他的生命周期函数我们都比较熟悉,所以这里主要讲一下新的两个函数getDerivedStateFromProps()和getSnapshotBeforeUpdate();

当我们需要基于Props更新State时,之前我们通常都做法是使用如下代码

class ExampleComponent extends React.Component{
  state = {
    isSuccess: false,
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.currentRow !== nextProps.currentRow) {
      this.setState({
        isSuccess:true
      });
    }
  }
}

尽管上面的代码本身并没有问题,但componentWillReceiveProps生命周期通常会被错误地用于解决问题。因此,该方法将被弃用。

既然 componentWillReceiveProps 要被废除了,那么,还有其他的方法能根据 prop 的改变更新 state 吗?这里就要用到新引进的那个静态方法了。这里说的静态和其他语言的概念是一样的,它是存在于类自身的方法,不依赖实例的创建。与一般的类方法的区别在于它不能访问 this 关键字,还有就是方法前面有个 static 修饰符。但是有一个问题,既然访问不到 this 了,那还怎么用 this.setState 来更新状态呢?答案是,“压根就不需要用这个方法了”,你只需要返回新的状态就行了,直接 return 出去,不需要用方法去设置。如果不需要更新状态,返回 null 就行了,此外,返回值的机制和使用 setState 的机制是类似的 —— 你只需要返回发生改变的那部分状态,其他的值会保留

class ExampleComponent extends React.Component{
  state = {
    isSuccess: false,
  };

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.currentRow !== prevState.lastRow) {
      return {
        isSuccess:true,
      };
    }
    return null;
  }
}

如果同时定义了 getDerivedStateFromProps 和 componentWillReceiveProps,只有 getDerivedStateFromProps 会被调用,同时 React 还会打印出警告信息。


同时定义两个方法.png

新的生命周期 getSnapshotBeforeUpdate()

class Example extends React.Component{

  getSnapshotBeforeUpdate(prevProps, prevState) {

    // ...  }

}

新的getSnapshotBeforeUpdate生命周期在更新之前被调用(例如,在DOM被更新之前)。此生命周期的返回值将作为第三个参数传递给componentDidUpdate。 (这个生命周期不是经常需要的,但可以用于在恢复期间手动保存滚动位置的情况。)

与componentDidUpdate一起,这个新的生命周期将覆盖旧版componentWillUpdate的所有用例。

总结

在React16中即将被废除的方法如下:

componentWillMount —— 即将废除,使用 componentDidMount 作为替代

componentWillUpdate—— 即将废除,使用 componentDidUpdate 作为替代

componentWillReceiveProps—— 即将废除,使用新引进的方法 static getDerivedStateFromProps

不过我们也不用慌,这些方法现在都可以正常使用,不影响,到 16.4 版本才会正式打上“已废除”的标记,真正移除可能要到 17.0 以后。

如果你开启了 StrictMode 或是 AsyncMode,它只会提示你方法已经废除了,不想看到这些提示信息可以使用如下方法替代:

UNSAFE_componentWillMount

UNSAFE_componentWillReceiveProps

UNSAFE_componentWillUpdate

这些改变旨在引导开发者作出最佳实践,这也有益于适应将来全面开放的异步渲染模式(这也是 React 16 “Fiber” 的首要目标)