1. 掛載卸載過程
1.1.constructor()
1.2.componentWillMount()
1.3.componentDidMount()
1.4.componentWillUnmount ()
2. 更新過程
2.1. componentWillReceiveProps (nextProps)
2.2.shouldComponentUpdate(nextProps,nextState)
2.3.componentWillUpdate (nextProps,nextState)
2.4.componentDidUpdate(prevProps,prevState)
2.5.render()
3. React新增的生命週期(個人補充)
3.1. getDerivedStateFromProps(nextProps, prevState)
3.2. getSnapshotBeforeUpdate(prevProps, prevState)
學習React的生命週期
React的生命週期從廣義上分爲三個階段:掛載、渲染、卸載
因此可以把React的生命週期分爲兩類:掛載卸載過程和更新過程。
React的生命週期圖:
1. 掛載卸載過程
1.1.constructor()
constructor()中完成了React數據的初始化,它接受兩個參數:props和context,當想在函數內部使用這兩個參數時,需使用super()傳入這兩個參數。
注意:只要使用了constructor()就必須寫super(),否則會導致this指向錯誤。
1.2.componentWillMount()
componentWillMount()一般用的比較少,它更多的是在服務端渲染時使用。它代表的過程是組件已經經歷了constructor()初始化數據後,但是還未渲染DOM時。
1.3.componentDidMount()
組件第一次渲染完成,此時dom節點已經生成,可以在這裏調用ajax請求,返回數據setState後組件會重新渲染
1.4.componentWillUnmount ()
在此處完成組件的卸載和數據的銷燬。
- clear你在組建中所有的setTimeout,setInterval
- 移除所有組建中的監聽 removeEventListener
- 有時候我們會碰到這個warning:
Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
原因:因爲你在組件中的ajax請求返回setState,而你組件銷燬的時候,請求還未完成,因此會報warning
解決方法:
componentDidMount() {
this.isMount === true
axios.post().then((res) => {
this.isMount && this.setState({ // 增加條件ismount爲true時
aaa:res
})
})
}
componentWillUnmount() {
this.isMount === false
}
2. 更新過程
2.1. componentWillReceiveProps (nextProps)
在接受父組件改變後的props需要重新渲染組件時用到的比較多
接受一個參數nextProps
通過對比nextProps和this.props,將nextProps的state爲當前組件的state,從而重新渲染組件
componentWillReceiveProps (nextProps) {
nextProps.openNotice !== this.props.openNotice&&this.setState({
openNotice:nextProps.openNotice
},() => {
console.log(this.state.openNotice:nextProps)
//將state更新爲nextProps,在setState的第二個參數(回調)可以打印出新的state
})
}
2.2.shouldComponentUpdate(nextProps,nextState)
主要用於性能優化(部分更新)
唯一用於控制組件重新渲染的生命週期,由於在react中,setState以後,state發生變化,組件會進入重新渲染的流程,在這裏return false可以阻止組件的更新
因爲react父組件的重新渲染會導致其所有子組件的重新渲染,這個時候其實我們是不需要所有子組件都跟着重新渲染的,因此需要在子組件的該生命週期中做判斷
2.3.componentWillUpdate (nextProps,nextState)
shouldComponentUpdate返回true以後,組件進入重新渲染的流程,進入componentWillUpdate,這裏同樣可以拿到nextProps和nextState。
2.4.componentDidUpdate(prevProps,prevState)
組件更新完畢後,react只會在第一次初始化成功會進入componentDidmount,之後每次重新渲染後都會進入這個生命週期,這裏可以拿到prevProps和prevState,即更新前的props和state。
2.5.render()
render函數會插入jsx生成的dom結構,react會生成一份虛擬dom樹,在每一次組件更新時,在此react會通過其diff算法比較更新前後的新舊DOM樹,比較以後,找到最小的有差異的DOM節點,並重新渲染。
3. React新增的生命週期(補充)
React新增生命週期
3.1. getDerivedStateFromProps(nextProps, prevState)
代替componentWillReceiveProps()。
老版本中的componentWillReceiveProps()方法判斷前後兩個 props 是否相同,如果不同再將新的 props 更新到相應的 state 上去。這樣做一來會破壞 state 數據的單一數據源,導致組件狀態變得不可預測,另一方面也會增加組件的重繪次數。
舉個例子:
// before
componentWillReceiveProps(nextProps) {
if (nextProps.isLogin !== this.props.isLogin) {
this.setState({
isLogin: nextProps.isLogin,
});
}
if (nextProps.isLogin) {
this.handleClose();
}
}
// after
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.isLogin !== prevState.isLogin) {
return {
isLogin: nextProps.isLogin,
};
}
return null;
}
componentDidUpdate(prevProps, prevState) {
if (!prevState.isLogin && this.props.isLogin) {
this.handleClose();
}
}
這兩者最大的不同就是:
在 componentWillReceiveProps 中,我們一般會做以下兩件事,一是根據 props 來更新 state,二是觸發一些回調,如動畫或頁面跳轉等。
在老版本的 React 中,這兩件事我們都需要在 componentWillReceiveProps 中去做。
而在新版本中,官方將更新 state 與觸發回調重新分配到了 getDerivedStateFromProps 與 componentDidUpdate 中,使得組件整體的更新邏輯更爲清晰。而且在 getDerivedStateFromProps 中還禁止了組件去訪問 this.props,強制讓開發者去比較 nextProps 與 prevState 中的值,以確保當開發者用到 getDerivedStateFromProps 這個生命週期函數時,就是在根據當前的 props 來更新組件的 state,而不是去做其他一些讓組件自身狀態變得更加不可預測的事情。
3.2. getSnapshotBeforeUpdate(prevProps, prevState)
代替componentWillUpdate。
常見的 componentWillUpdate 的用例是在組件更新前,讀取當前某個 DOM 元素的狀態,並在 componentDidUpdate 中進行相應的處理。
這兩者的區別在於:
在 React 開啓異步渲染模式後,在 render 階段讀取到的 DOM 元素狀態並不總是和 commit 階段相同,這就導致在
componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀態是不安全的,因爲這時的值很有可能已經失效了。
getSnapshotBeforeUpdate 會在最終的 render 之前被調用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態是可以保證與 componentDidUpdate 中一致的。
此生命週期返回的任何值都將作爲參數傳遞給componentDidUpdate()。