React 的生命周期本質(zhì)上就是一系列的鉤子函數(shù),可以分為 3 個(gè)時(shí)期:掛載佣耐、更新和卸載铲球。React 16 還新增錯(cuò)誤處理的鉤子函數(shù)。要掌握 React晰赞,生命周期是必不可少的一部分。
注意:本文只對(duì)目前最新的 React 生命周期展開(kāi)詳解(v16.4.0)选侨。
生命周期流程圖
組件創(chuàng)建時(shí)的生命周期
static getDerivedStateFromProps(nextProps, prevState)
該周期函數(shù)接收兩個(gè)參數(shù)掖鱼,新的屬性作為第一個(gè)參數(shù),先前的狀態(tài)作為第二個(gè)參數(shù)援制。當(dāng)函數(shù)返回 null 時(shí)戏挡,代表新的屬性不需要更新?tīng)顟B(tài);當(dāng)函數(shù)返回了一個(gè)對(duì)象晨仑,對(duì)象中的屬性則會(huì)被更新到 State 中褐墅。如下:
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.currentId 拆檬!== nextProps.itemId) {
return {
currentId: nextProps.itemId
};
}
return null;
}
上圖意思是,當(dāng)新屬性中的 itemId 與當(dāng)前 State 的 currentId 不一致時(shí)妥凳,則執(zhí)行 currentId 狀態(tài)的更新竟贯,否則返回 null,不執(zhí)行任何的更新逝钥。
簡(jiǎn)單來(lái)說(shuō)屑那,如果你的組件中,接收新的屬性不需要觸發(fā)狀態(tài)的更新艘款,可以忽略該函數(shù)持际,或在該函數(shù)中直接返回 null。
值得一提的是哗咆,該周期函數(shù)getDerivedStateFromProps(){...}
是一個(gè)靜態(tài)函數(shù)蜘欲,無(wú)法訪問(wèn)組件的實(shí)例 this,所以在該函數(shù)中沒(méi)辦法訪問(wèn) this.props 和 this.state晌柬。
componentDidMount
該函數(shù)代表組件實(shí)例化完成姥份,這個(gè)時(shí)候非常適合執(zhí)行
- 網(wǎng)絡(luò)請(qǐng)求(Ajax)
- 事件訂閱
組件更新時(shí)的生命周期
static getDerivedStateFromProps
該周期函數(shù)在組件的屬性和狀態(tài)更新時(shí)都會(huì)被觸發(fā),用法等同組件創(chuàng)建時(shí)的 getDerivedStateFromProps
函數(shù)空繁。
shouldComponentUpdate(nextPorps, nextState)
該函數(shù)接收新的屬性作為第一個(gè)參數(shù)殿衰,新的狀態(tài)作為第二個(gè)參數(shù)。當(dāng)函數(shù)返回 true 的時(shí)候盛泡,周期函數(shù)會(huì)繼續(xù)往下執(zhí)行 render 渲染闷祥;當(dāng)函數(shù)返回 false,周期函數(shù)則會(huì)中止于此傲诵,并停止下面的渲染凯砍。如果不設(shè)置,這個(gè)函數(shù)會(huì)默認(rèn)返回 true拴竹。
利用好這個(gè)周期函數(shù)的特性悟衩,我們可以避免無(wú)用的渲染,提升頁(yè)面的性能栓拜。
getSnapshotBeforeUpdate(prevProps, prevState)
該周期函數(shù)的時(shí)期處在 render
函數(shù)執(zhí)行之后和組件 DOM 渲染之前座泳。它讓你的組件能在當(dāng)前的值可能要改變前獲得它們。該函數(shù)返回的任何值將作為 componentDidUpdate
周期函數(shù)的第三個(gè)參數(shù)幕与。
componentDidUpdate(prevProps, prevState, snapshot)
componentDidUpdate
函數(shù)會(huì)在更新發(fā)生后立即被調(diào)用挑势。
我們可以在該方法中修改組件的狀態(tài)以進(jìn)行 DOM 的更新。同時(shí)啦鸣,這也是一個(gè)適合發(fā)送網(wǎng)絡(luò)請(qǐng)求(Ajax)的地方潮饱,我們可以通過(guò)對(duì)比當(dāng)前屬性和舊屬性來(lái)判斷是否需要發(fā)送網(wǎng)絡(luò)請(qǐng)求。
組件掛載時(shí)的生命周期
componentWillUnmount
componentWillUnmount
函數(shù)在組件被卸載和銷毀之前被調(diào)用诫给。我們可以在該方法里做清理工作香拉,例如解綁定時(shí)器啦扬,取消網(wǎng)絡(luò)請(qǐng)求,清理任何在 componentDidMount
環(huán)節(jié)創(chuàng)建的 DOM 元素凫碌,取消事件訂閱扑毡。
異常處理的周期函數(shù)
componentDidCatch
錯(cuò)誤邊界是一個(gè) React 組件。錯(cuò)誤邊界組件捕捉發(fā)生在子組件樹(shù)中任意地方的 JavaScript 錯(cuò)誤证鸥,打印錯(cuò)誤日志僚楞,并且顯示回退的用戶界面。錯(cuò)誤邊界可以捕捉組件渲染期間枉层、生命周期方法中和子組件構(gòu)造函數(shù)中的錯(cuò)誤泉褐。
如果定義了這一生命周期方法,一個(gè)類組件將成為一個(gè)錯(cuò)誤邊界組件鸟蜡。我們可以在錯(cuò)誤邊界組件捕獲到 JavaScript 錯(cuò)誤的時(shí)候膜赃,顯示回退的用戶界面。
以下是一個(gè)錯(cuò)誤邊界組件
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// 顯示錯(cuò)誤發(fā)生的回退視圖
this.setState({ hasError: true });
// 也可以上報(bào)錯(cuò)誤到服務(wù)器
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// 定制任意的回退視圖
return <h1>頁(yè)面被外星人偷走了</h1>;
}
return this.props.children;
}
}
然后將它作為常規(guī)組件
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
該 componentDidCatch 方法的工作方式類似于 JavaScript catch {} 塊揉忘,但它一個(gè)適用于組件的 catch 塊跳座。實(shí)際上,大多數(shù)情況下泣矛,我們只需要聲明一次錯(cuò)誤邊界組件疲眷,并在整個(gè)應(yīng)用程序中使用它。
請(qǐng)注意您朽,錯(cuò)誤邊界僅捕獲組件樹(shù)中處于它們子層級(jí)組件中的錯(cuò)誤狂丝,錯(cuò)誤邊界本身的錯(cuò)誤無(wú)法捕獲。如果錯(cuò)誤邊界組件自身報(bào)錯(cuò)哗总,則錯(cuò)誤將傳播到其上方最接近的錯(cuò)誤邊界几颜。
參考:新版React生命周期圖