before React 16.3

父子组件样例:
//parent.jsx
//child.jsx

React父子组件挂载阶段:
parent constructor
->parent componentWillMount
->parent render
->child constructor
->child componentWillMount
->child render
->child componentDidMount
->parent componentDidMountReact父子组件更新阶段:
parent shouldComponentUpdate
//shouldComponentUpdate的返回值 如果为true则向下执行 否则false将不会再向下执行
->parent componentWillUpdate
->parent render
->child componentWillReceiveProps
->child shouldComponentUpdate
->child componentWillUpdate
->child render
->child componentDidUpdate
->parent componentDidUpdateReact卸载阶段:
componentWillUnmountconstructor( props ):React的构造函数一般用来初始化state和为事件处理函数绑定实例,如果需要引入订阅或者副作用则请使用componentDidMount。
componentWillMount( ):它在render之前被调用,但不要在这里加入this.setState因为它并不会执行,而且不要在这个生命周期函数里去获取服务端数据,因为在render之前不会返回数据,所以它一般只用于服务端渲染。
componentWillReceiveProps( nextProps ): 一般用于子组件中使用,会在已挂载的父组件中接收新的props时被调用,可以用来比较this.props和nextProps的值去使用this.setState进行state变化。 需要注意的是,如果父组件导致子组件重新渲染,即使props没有改变,此函数也会被执行一次!在挂载过程中,父组件初始化props不会导致子组件的此函数被调用,只有当父组件的props发生更新后调用此方法。
shouldComponentUpdate( nextProps, nextState ) : 当props或者state发生变化时,此函数会在渲染执行前被调用,默认返回值是true,但是使用该函数时必须要有一个Boolean返回值,否则浏览器会提示错误。此方法仅作为性能优化存在,比较this.props和nextProps还有this.state和nextState的值,返回false则React可以跳过此次更新,也不会再去调用componentWillUpdate、render、componentDidUpdate,但是此时子组件依然可以根据state的改变重新渲染。
componentWillUpdate( nextProps, nextState ) : 当组件的props或者state发生变化时,会在渲染执行之前被调用,但shouldComponentUpdate返回false时,此生命周期函数将不会被执行。在这里可以使用this.setState,但需要进行his.props和nextProps还有this.state和nextState的值对比后再去改变state的值,否则将会造成死循环,浏览器内存占满后崩溃,建议在shouldComponentUpdate中去改变state的值。
render( ) : 当render被调用时,它会检查this.state和this.props的变化返回 React元素、数组或者Fragments、portals、字符串或者数值类型、boolean类型或者null。
componentDidMount( ) : 会在组件装载后立即被调用,可用来通过网络请求获取数据,直接使用this.setState更新state的值,也可以添加事件订阅,但需要在componentWillUnmount进行卸载订阅。
componentDidUpdate( preProps,preState ) : 会在更新后立即被调用,首次渲染不会执行此方法,但shouldComponentUpdate返回false时,此生命周期函数将不会被执行。 当组件更新完以后,对比更新前后props的值,如果不相等则可以去执行this.setState或者网络请求,但是没有条件比对直接去执行其他操作将会造成死循环。
componentWillUnmount( ) : 会在组件卸载或者销毁之前被调用。此函数用来必要的清除操作,比如clearInterval清除定时器,取消网络请求或者清除在componentDidMount中使用的订阅。这里不应该使用this.setState,因为组件永远不会重新渲染。
after React 16.3

static getDerivedStateFromProps( props, state ) : 会在render之前被调用,初次挂载或者更新后都会被调用,它应返回一个对象去更新state,返回null则不更新任何内容。这个生命周期函数也间接取代了老版本React中的componentWillReceiveProps、componentWillMount、componentWillUpdate这三个生命周期函数,但并不是完全取代,例如componentWillReceiveProps在只有父组件重新渲染时触发,但此函数在每次渲染之前都会被触发!它一般适用于让state的值一直被props所控制。
getSnapshotBeforeUpdate( preProps, preState ) : 会在最近一次渲染之前被调用到,使得它可以在组件更新之前从Dom中捕捉一些信息( 如滚动位置 ) , 此函数的任何返回值都将作为参数传递到componentDidUpdate的第三个参数里,此用法可用来UI处理滚动位置,否则尽量不要去使用它!返回值是Snapshot值或者null。
componentDidUpdate( preProps, preState, snapshot ) : 用法同之前的React版本一致,但如果使用了getSnapshotBeforeUpdate( ),则它的返回值将作为componentDidUpdate的第三个返回值,否则此参数为unidentified。
Props直接给State传值的问题:
应用场景例如 每个用户注册后都会有自己设置的密码,这时存储好的密码就是props,初始化为空的密码就是state,我们需要去实现修改密码的功能,做法肯定是将props直接传递给state,然后改变state的值再传输到服务端完成此功能。
这个功能实现过程中,我们不能直接将props赋值给state,只有监听props变化后才去改变state,但有时候会遇到特殊情况
componentWillReceiveProps(nextProps){
if(nextProps.password !== this.props.password){
this.setState({
password: nextProps.password
})
}
}看上去上面的方法能解决问题,但是再想想看,如果切换用户进行修改密码时,前后用户的密码一模一样,则state不会进行改变,页面也不会重新渲染,也就相当于直接泄露密码了。
//before React 16.3
componentWillReceiveProps(nextProps){
if(nextProps.userId !== this.props.userId){
this.setState({
password: nextProps.password
})
}
}
//after React 16.3
state = {
userId : this.props.userId,
password : this.props.password
}
static getDerivedStateFromProps( props,state ){
if( props.userId !== state.userId ){
return{
userId: props.userId
password: props.password
}
}
return null;
}这时判断state改变条件改成了监听用户的ID的变化,此时每次切换用户进行修改密码时都会使页面重新渲染,每次props的值都将重新赋值给state。
如有不对,麻烦请指出错误。