react生命周期再学习、了解

2020-09-03  本文已影响0人  淡退

组件生命周期的三个阶段

  1. Mounting(加载阶段)

  2. Updating(更新阶段)

  3. Unmounting(卸载阶段)

旧的生命周期

image.png

Mounting(加载阶段:涉及6个钩子函数)

constructor()
加载的时候调用一次,可以初始化state
getDefaultProps()

设置默认的props,也可以用dufaultProps设置组件的默认属性。

1、如果是extend 方式创建的组件,不可以getDefaultProps设置默认的props值,放在类名.defaultProps = {}中

class PreDes extends React.Component {
 static defaultProps = {
     datatext:"sssssss"
 }
 render(){
    return ( <div> {this.props.datatext } </div> )
  }
}
// 或者
PreDes.defaultProps = {
  datatext:"sssssss"
}
export default PreDes;

2、在React.createClass中, getDefaultProps属性是一个返回Object来创建初始props的函数。

import React from 'react';

const Contacts = React.createClass({
    getDefaultProps() {
        return {
          datatext:"sssssss"
        };
    },
    render() {
        return ( <div>{this.props. datatext }</div>
      } 
    }
});
export default Contacts;
getInitialState()

初始化state,可以直接在constructor中定义this.state或者在class声明state。

在class中该方法已经废弃

下面两种写法与react没有关系,是es6支持的语法
实例属性的新写法

state={
    newAddress: 'xxxxx',
}    
// 或者
constructor(props){
         super(props);
         this.state={
             newAddress: this.props.address,
         }
}

getInitialState()主要是在类组件中来进行初始化state的作用。

import React from 'react';

const Contacts = React.createClass({
    getInitialState() {
        return {
          datatext:"sssssss"
        };
    },
    render() {
        return ( <div>{this.state.datatext }</div>
      } 
    }
});
export default Contacts;
componentWillMount()

组件加载时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state

render()

react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行

componentDidMount()

组件渲染之后调用,只调用一次

Updating(更新阶段:涉及5个钩子函数)

componentWillReceiveProps(nextProps)

组件加载时不调用,组件接受新的props时调用

在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态或者是触发子组件内的某些方法,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用

在这里我们可以比较两个props从而对本组件的state作出安全的变更。

如果在这个方法中调用了一个方法,而这个方法中使用了this.props中的属性,你会发现数据并没有改变

componentWillReceiveProps(nextProps){
//componentWillReceiveProps方法中第一个参数代表即将传入的新的Props
    if (this.props.sharecard_show !== nextProps.sharecard_show){
        //在这里我们仍可以通过this.props来获取旧的外部状态
        //通过新旧状态的对比,来决定是否进行其他方法
        if (nextProps.sharecard_show){
            this.handelConsole();
        }
    }
}

handelConsole = () => {
    console.log(this.props.sharecard_show)  
    // 这里不是最新的props。
}
shouldComponentUpdate(nextProps, nextState)

组件接收到新的props或者state时调用,return true就会更新dom(使用diff算法更新),return false能阻止更新(不调用render)

componentWillUpdata(nextProps, nextState)

组件加载时不调用,只有在组件将要更新时才调用,此时可以修改state

render()

react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行

componentDidUpdate(prevProps, prevState, snapshot)

组件加载时不调用,组件更新完成后调用,因此在 componentDidUpdate 中可以在组件更新的时候,对 DOM 进行一些操作,同时这个方法有三个参数,可以通过参数比较比如 props ,能够判断是否需要网络请求新的数据等,比如官方文档给的示例如下:

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}
旧生命周期总结
image.png

Unmounting(卸载阶段:涉及1个钩子函数)

componentWillUnmount()

组件渲染之后调用,只调用一次

React新增的生命周期

弃用:

  1. componentWillMount、
  2. componentWillReceiveProps,
  3. componentWillUpdate

新增:

  1. getDerivedStateFromProps、
  2. getSnapshotBeforeUpdate

来代替弃用的三个钩子函数。

React16并没有删除这三个钩子函数,但是不能和新增的钩子函数(getDerivedStateFromProps、getSnapshotBeforeUpdate)混用,React17将会删除componentWillMount、componentWillReceiveProps,componentWillUpdate

新增了对错误的处理(componentDidCatch)

getDerivedStateFromProps(nextProps, prevState)
class ExampleComponent extends React.Component{
  state = {
    isSuccess: false,
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.currentRow !== nextProps.currentRow) {
      this.setState({
        isSuccess:true
      });
    }
    // 在这里进行异步操作或者更新状态
    this.setState({
        type: props.type,
    });
    this._doAsyncOperation();
  }
}

老版本中的componentWillReceiveProps()方法判断前后两个 props 是否相同,如果不同再将新的 props 更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。

当外部多个属性在很短的时间间隔之内多次变化,就会导致componentWillReceiveProps被多次调用。这个调用并不会被合并,如果这次内容都会触发异步请求,那么可能会导致多个异步请求阻塞。

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

该方法是一个静态方法,与一般的类方法的区别在于它不能访问 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;
  }
getSnapshotBeforeUpdate(prevProps, prevState)

这个新更新代替componentWillUpdate。
常见的 componentWillUpdate 的用例是在组件更新前,读取当前某个 DOM 元素的状态,并在 componentDidUpdate 中进行相应的处理。

这两者的区别在于:

  1. 在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在
    componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
  2. getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。
    此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。

参考dome: getSnapshotBeforeUpdate案例
参考文章:React新生命周期--getDerivedStateFromProps、getSnapshotBeforeUpdate

上一篇下一篇

猜你喜欢

热点阅读