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