美文网首页
react生命周期再学习、了解

react生命周期再学习、了解

作者: 淡退 | 来源:发表于2020-09-03 16:08 被阅读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

    相关文章

      网友评论

          本文标题:react生命周期再学习、了解

          本文链接:https://www.haomeiwen.com/subject/bxhosktx.html