理解React-组件生命周期
作者-Bartosz Szczeciński: 原文
React提供給開發(fā)者很多方法或‘鉤子’,調(diào)用于一個組件的生命周期,使我們更新UI和app state。了解何時使用哪些對正確理解如何使用React至關(guān)重要。
constructor
constuctors是OOP的基礎(chǔ)——一個無論何時一個新object被創(chuàng)建時被調(diào)用的特殊函數(shù)。調(diào)用一個特殊函數(shù)super非常重要,在我們的class extent任何其它class(也有定義了constructor)時。調(diào)用此特殊函數(shù)將call 我們parent class的constructor且允許初始化其本身。此即為何我們只有在初始化地call了super時才有權(quán)限訪問this.props的原因。
如上所述,constructor對于構(gòu)建我們組件——創(chuàng)建任何領(lǐng)域(以this.開始的變量)或者初始化以接收到的props為基礎(chǔ)的state——非常完美。
這也是你通過在直接覆蓋this.state之處期待change/set state僅有的字段。在別的其它實例上記得用this.setState.
DO
- set initial state
- 若未用class屬性語法-準(zhǔn)備所有class 字段和bind 將作為callback傳遞的函數(shù)。
DON'T
- cause any side effects (AJAX calls etc.)
componentWillMount
這是一個特殊情況 - componentWillMount與構(gòu)造函數(shù)沒有多大區(qū)別 - 它只在初始安裝生命周期中被調(diào)用一次。 從歷史上看,使用componentWillMountover構(gòu)造函數(shù)有一些原因,請參閱此react-redux問題,但請記住,此處描述的練習(xí)已被棄用。
很多人會試圖使用這個函數(shù)來發(fā)送請求來獲取數(shù)據(jù),并希望在初始渲染準(zhǔn)備好之前數(shù)據(jù)可用。 情況并非如此 - 當(dāng)請求在渲染之前被初始化時,在渲染被調(diào)用之前它將不能完成。
此外,隨著對React Fiber的更改(post React 16 beta版本),此函數(shù)最終可能會在初始渲染被調(diào)用之前調(diào)用多次,因此可能會導(dǎo)致觸發(fā)多重副作用。 由于這個事實,不推薦使用這個函數(shù)來產(chǎn)生任何副作用。
值得注意的是,在使用服務(wù)器端渲染時調(diào)用此函數(shù),而在這種情況下,它不會在服務(wù)器上調(diào)用對應(yīng)的componentDidMount,而是在客戶端上調(diào)用。 所以如果在服務(wù)器部分需要一些副作用,這個函數(shù)應(yīng)該被用作例外。
此函數(shù)中使用的setState是“空閑”的,不會觸發(fā)重新渲染。
DO
- update state 通過 this.setState
- perform last minute optimization(執(zhí)行最后一分鐘優(yōu)化)
- 僅在SSR造成side-effects (AJAX calls etc.)
DON'T
- 不在CS造成side-effects (AJAX calls etc.)
componentWillReceiveProps(nextProps)
這個函數(shù)將在每個更新生命周期中由props變化(父元素重新渲染)調(diào)用,并且將傳遞所有props傳遞的對象圖,無論自上次重新渲染后props值是否已經(jīng)改變亦或自前個渲染階段。
這個函數(shù)是理想的,如果你有一個組件的狀態(tài)部分取決于從父組件傳遞的props作為調(diào)用this.setState在這里不會導(dǎo)致額外的渲染調(diào)用。
請記住,由于所有props都調(diào)用了該函數(shù),所以即使對那些沒有改變的props,開發(fā)人員也會執(zhí)行檢查以確定實際值是否發(fā)生了變化,例如:
componentWillReceiveProps(nextProps) {if(nextProps.myProp !== this.props.myProps) {// nextProps.myProp has a different value than our current prop// so we can perform some calculations based on the new value} } 復(fù)制代碼由于使用React Fiber(16階測試版)這個功能可能會在實際調(diào)用renderfunction之前多次調(diào)用,因此不建議在此使用任何副作用導(dǎo)致的操作。
DO
- sync state to props(同步化state到props)
DON'T
- 造成side-effects (AJAX calls etc.)
shouldComponentUpdate(nextProps, nextState, nextContext)
默認(rèn)情況下,所有基于類的組件都會在它們接收到的props,其狀態(tài)或環(huán)境發(fā)生變化時重新render自己。 如果重新渲染組件是計算重啟(例如生成圖表)或者出于某些性能原因不推薦使用,則開發(fā)人員可以訪問將在update cycle中調(diào)用的特殊函數(shù)。
這個函數(shù)將在內(nèi)部調(diào)用props,state和object的下一個值。 開發(fā)人員可以使用它們來驗證更改是否需要重新渲染,并返回false以防止重新渲染發(fā)生。 在其他情況下,您預(yù)計會返回true。
DO
- 用于提高perfomance
DON'T
- 造成side-effects (AJAX calls etc.)
- call this.setState
componentWillUpdate(nextProps, nextState)
如果shouldComponentUpdate函數(shù)未被使用,或者它決定組件在此渲染周期中應(yīng)更新,則將調(diào)用另一個生命周期函數(shù)。 此函數(shù)通常用于在state的某些部分基于props時,執(zhí)行狀態(tài)和props同步。
在實現(xiàn)shouldComponentUpdate的情況下,可以使用此函數(shù)而不是componentWillReceiveProps,因為只有在實際重新渲染組件時才會調(diào)用此函數(shù)。
與所有其他componentWill *函數(shù)類似,此函數(shù)可能在渲染前最終調(diào)用多次,因此不建議在此執(zhí)行導(dǎo)致操作的副作用。 DO
- synchronize state to props
DON'T
- 造成side-effects (AJAX calls etc.)
componentDidUpdate(prevProps, prevState, prevContext)
這個函數(shù)將在渲染完成后在每個重新渲染周期中被調(diào)用。 這意味著您可以確定組件及其所有子組件已正確render其自身。
由于這是唯一保證在每個重新render周期中僅被調(diào)用一次的函數(shù),因此建議將此函數(shù)用于任何導(dǎo)致操作的副作用。 與componentWillUpdate和componentWillReceiveProps類似,即使這些值沒有發(fā)生實際更改,也會使用以前的props,state和context的object映射來調(diào)用此函數(shù)。 因為開發(fā)人員需要手動檢查給定的值是否發(fā)生了變化,然后才能執(zhí)行各種更新操作:
componentDidUpdate(prevProps) {if(prevProps.myProps !== this.props.myProp) {// this.props.myProp has a different value// we can perform any operations that would // need the new value and/or cause side-effects // like AJAX calls with the new value - this.props.myProp} } 復(fù)制代碼DO
- 造成side-effects (AJAX calls etc.)
DON'T
- call this.setState 因其可致re-render
上述規(guī)則的一個例外是基于某些DOM屬性更新狀態(tài),只有在組件重新呈現(xiàn)后才能計算該屬性(例如,某些DOM節(jié)點的位置/維度)。 請注意防止更新,如果值實際上沒有更改,可能會導(dǎo)致渲染循環(huán)。
componentDidCatch(errorString, errorInfo)
React 16中的新增功能 - 此生命周期方法的特殊之處在于它可以對發(fā)生在子組件中的事件作出反應(yīng),特別是對任何子組件中發(fā)生的任何未捕獲錯誤。
通過這個添加,你可以讓你的父母元素處理錯誤 - 例如 - 設(shè)置錯誤信息狀態(tài)并在其渲染中返回適當(dāng)?shù)南?#xff0c;或者登錄到報告系統(tǒng),例如:
componentDidCatch(errorString, errorInfo) {this.setState({error: errorString});ErrorLoggingTool.log(errorInfo); } render() {if(this.state.error) return <ShowErrorMessage error={this.state.error} />return (// render normal component output); } 復(fù)制代碼發(fā)生錯誤時,該函數(shù)將被調(diào)用:
- errorString - 錯誤的.toString()消息
- errorInfo - 具有單個字段componentStack的對象,它表示堆棧跟蹤返回錯誤發(fā)生的位置,例如:
componentDidMount
這個函數(shù)在給定組件的整個生命周期中只會被調(diào)用一次,并且它被調(diào)用表示組件及其所有子組件被正確渲染。
由于這個函數(shù)被保證只被調(diào)用一次,因此它是完成AJAX請求等引起副作用的操作的理想選擇。
DO
- 造成side-effects (AJAX calls etc.)
DON'T
- call this.setState 因其可致re-render
上述規(guī)則的一個例外是基于某些DOM屬性更新狀態(tài),只有在組件重新呈現(xiàn)后才能計算該屬性(例如,某些DOM節(jié)點的位置/維度)。 請注意防止更新,如果值實際上沒有更改,可能會導(dǎo)致渲染循環(huán)。
componentWillUnmount
如果它使用定時器(setTimeout,setInterval),打開套接字或執(zhí)行我們需要在不再需要時關(guān)閉/移除的任何操作,則使用此函數(shù)在組件后面“清除”。
DO
- remove any timers or listeners created in lifespan of the component
DON'T
- call this.setState, start new listeners or timers
Component cycles
組件可能re-render有多種原因,并且每個組件中都會調(diào)用不同的函數(shù),以便開發(fā)人員更新組件的某些部分。
- Component creation(組件創(chuàng)建)
第一個循環(huán)是組件的創(chuàng)建,這通常是在解析的JSX?中第一次遇到組件時發(fā)生的:
- Component re-rendering due to re-rendering of the parent component(由于父組件更新而組件更新)
- Component re-rendering due to internal change (e.g. a call to this.setState())( 由于內(nèi)部改變的組件更新)
- Component re-rendering due to call to this.forceUpdate(由于call this.forceUpdate而re-render的組件)
- Component re-rendering due to catching an error(由于捕獲錯誤而更新組件)
在React 16中引入了“ErrorBoundaries”。 一個組件可以定義一個特殊的層,它可以捕獲錯誤并提供一個新的生命周期方法 - componentDidCatch - 它允許開發(fā)人員提供自我修復(fù)操作以恢復(fù)或優(yōu)雅地處理錯誤。
Shoutout to@James_k_nelson,他剛剛發(fā)布了一個componentWillReceiveProps模擬器,你可以在reactarmory.com/guides/life…找到并使用它。
總結(jié)
以上是生活随笔為你收集整理的理解React-组件生命周期的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 70+漂亮且极具亲和力的导航菜单设计推荐
- 下一篇: 利用angular4和nodejs-ex