只执行一次: constructor、componentWillMount、componentDidMount

执行多次:子组件的componentWillReceiveProps、componentWillUpdate、render 、componentDidUpdate

有条件的执行:componentWillUnmount(页面离开,组件销毁时)

不执行的:根组件(ReactDOM.render在DOM上的组件)的componentWillReceiveProps(因为压根没有父组件给传递props)

 

 引自:(https://www.cnblogs.com/faith3/p/9216165.html) 

什么时候该用componentWillReceiveProps?

 

是否每个子组件都需要componentWillReceiveProps生命周期函数来更新数据吗? 你的原则是??

 

A、开始前首先需要知道componentWillReceiveProps函数有一个参数nextProps,它是一个 { 对象 } ,从单词就可以看出它是update时候(也就是下一次)父组件传递过来的props。

B、还要知道 "第一条中" 所讲解的有些生命周期函数只执行一次,而有的执行多次,其中componentWillReceiveProps执行多次,而constructor等执行一次。

C、还需知道在子组件中每次传递过来的this.props对象其实和componentWillReceiveProps的nextProps是一样的,都是最新的。

D、由"第一条"得知: componentWillReceiveProps生命周期是在更新子组件最先执行的,优先于compoentWillUpdate,更优先于render。

E、render函数里不能使用setState(),否则会造成死循环。

 

转自:https://segmentfault.com/a/1190000017175195

React生命周期分为了 挂载(装配) 、 更新 、 卸载 以及 捕错 四个状态阶段。每种状态里需要执行若干个生命周期函数,这些函数可能会在不同的阶段里重新被调用。

1.挂载(装配)

  • constructor(),构造函数会在装配前调用。
  • static getDerivedStateFromProps(nextProps,prevState)从props得到派生的state,组件实例化后接受新属性时调用,返回一个对象以更新状态,或返回null表明不需要更新状态。
  • componentWillMount()装配前立刻调用,发生在render()之前.组件挂载到DOM前调用,且只会被调用一次,在这边调用this.setState不会引起组件重新渲染,也可以把写在这边的内容提前到constructor()中,所以项目中很少用。
  • render(),必须的钩子函数,不应该改变组件的状态,且不与浏览器交互,根据组件的props和state(无两者的重传递和重赋值,论值是否有变化,都可以引起组件重新render) ,return 一个React元素(描述组件,即UI),不负责组件实际渲染工作,之后由React自身根据此元素去渲染出页面DOM。render是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有副作用),不能在里面执行this.setState,会有改变组件状态的副作用作者:aermin
  • componentDidMount():组件装配后立刻调用,实现远端网络请求的地方,且只会被调用一次

2.更新(属性或状态发生改变后,会触发一次更新,组件重新渲染,下述方法会被调用。

  •  componentWillReceiveProps(nextProps) / UNSAFE_componentWillReceiveProps()

            在挂载了的组件接收到新属性前调用。推荐使用getDerivedStateFromProps生命周期而不是该函数。此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新props。但父组件render方法的调用不能保证重传给当前组件的props是有变化的,所以在此方法中根据nextProps和this.props来查明重传的props是否改变,以及如果改变了要执行啥,比如根据新的props调用this.setState出发当前组件的重新

  •  static getDerivedStateFromProps():getDerivedStateFromProps本来(React v16.3中)是只在创建和更新(由父组件引发部分),也就是不是不由父组件引发,那么getDerivedStateFromProps也不会被调用,如自身setState引发或者forceUpdate引发。

  • shouldComponentUpdate() : 在挂载了的组件属性变化和状态变化时调用。通过控制返回的boolean值告诉React是否重新渲染该组件,
    • shouldComponentUpdate(nextProps, nextState)

    此方法通过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新停止,以此可用来减少组件的不必要渲染,优化组件性能。

    ps:这边也可以看出,就算componentWillReceiveProps()中执行了this.setState,更新了state,但在render前(如shouldComponentUpdate,componentWillUpdate),this.state依然指向更新前的state,不然nextState及当前组件的this.state的对比就一直是true了

  • componentWillUpdate() / UNSAFE_componentWillUpdate()

    当接收到新属性或状态时UNSAFE_componentWillUpdate()渲染前被立即调用,若shouldComponentUpdate()返回false,UNSAFE_componentWillUpdate()将不会被调用。

  •   componentDidUpdate()

            在更新发生后立即被调用。适合发送请求的地方此方法在组件更新后被调用,可以操作组件更新的DOM,prevProps和prevState这两个参数指的是组件更新前的props和state

3.卸载

 

 

  •  1. componentWillUnmount()

  • componentWillUnmount()组件被卸载和销毁之前立刻调用。可以在该方法里处理任何必要的清理工作,例如解绑定时器,取消网络请求清理任何在componentDidMount环节创建的DOM元素

4.错误处理

  • 1. componentDidCatch(error, info)

          错误边界捕捉发生在子组件树中任意地方的JavaScript错误,一个错误边界并不能捕捉它自己内部的错误。

造成组件更新有两类(三种)情况:

  • 1.父组件重新render

父组件重新render引起子组件重新render的情况有两种,内容及代码修引自xiaoyann的回答

a. 直接使用,每当父组件重新render导致的重传props,子组件将直接跟着重新渲染,无论props是否有变化。可通过shouldComponentUpdate方法优化。

class Child extends Component {
   shouldComponentUpdate(nextProps){ // 应该使用这个方法,否则无论props是否有变化都将会导致组件跟着重新渲染
        if(nextProps.someThings === this.props.someThings){
          return false
        }
    }
    render() {
        return <div>{this.props.someThings}</div>
    }
}

b.在componentWillReceiveProps方法中,将props转换成自己的state

class Child extends Component {
    constructor(props) {
        super(props);
        this.state = {
            someThings: props.someThings
        };
    }
    componentWillReceiveProps(nextProps) { // 父组件重传props时就会调用这个方法
        this.setState({someThings: nextProps.someThings});
    }
    render() {
        return <div>{this.state.someThings}</div>
    }
}

根据官网的描述

在该函数(componentWillReceiveProps)中调用 this.setState() 将不会引起第二次渲染。

是因为componentWillReceiveProps中判断props是否变化了,若变化了,this.setState将引起state变化,从而引起render,此时就没必要再做第二次因重传props引起的render了,不然重复做一样的渲染了

  • 2.组件本身调用setState,无论state有没有变化。可通过shouldComponentUpdate方法优化。
class Child extends Component {
   constructor(props) {
        super(props);
        this.state = {
          someThings:1
        }
   }
   shouldComponentUpdate(nextStates){ // 应该使用这个方法,否则无论state是否有变化都将会导致组件重新渲染
        if(nextStates.someThings === this.state.someThings){
          return false
        }
    }

   handleClick = () => { // 虽然调用了setState ,但state并无变化
        const preSomeThings = this.state.someThings
         this.setState({
            someThings: preSomeThings
         })
   }

    render() {
        return <div onClick = {this.handleClick}>{this.state.someThings}</div>
    }
}

此阶段分为componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate

 

posted on 2019-09-06 17:18  四月妹  阅读(508)  评论(0编辑  收藏  举报