只执行一次: 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