原文連接:React Lifecycle Methods- how and when to use themjavascript
做者:Scott DomesFollow Front-End/Mobile Developer @ MuseFind.
翻譯:johannlaijava
上名這個圖片,就是 React 組件的生命週期,從造成 (pre-mounting)到銷燬 (unmounting)的過程。react
React 的優雅之處就在於,它把複雜的 UI 分解成很小的部分。 咱們不只僅能夠劃分咱們的應用,並且咱們還能夠定製咱們每個組件。canvas
經過組件的生命週期方法,咱們能夠控制當UI的每一個微小部分渲染,更新,考慮從新渲染,而後徹底消失時會發生什麼事情。網絡
讓咱們開始吧!ide
您的組件將很快就會出如今屏幕上面。這個大塊的渲染功能與其全部精美的 JSX 同樣,即將被調用。那你想作什麼?函數
答案是... 可能不是不少。 可是 componentWillMount
的確用處不會太大。佈局
關於 componentWillMount 的事情是,沒有組件能夠玩,因此你不能作任何涉及DOM的事情。(譯者:由於還沒渲染組件)性能
此外,自從您的組件的構造函數( constructor )被調用以來,沒有任何變化,可是,不管如何,您應該在其中設置組件的默認配置。ui
export default calss Sidebar extends Component { constructor(props) { super(props) this.state = { analyticsOpen: false, requirementsOpen: false, barndInfoOpen: false } } }
如今您的組件處於默認位置,幾乎全部的東西都應該由其他的組件代碼來處理,而不須要額外的生命週期方法。
例外是隻能在運行時完成的任何設置,說白了也就是鏈接到外部 API 。舉個栗子,若是您的應用程序使用Firebase,則須要在應用程序首次掛載(mounting)時進行設置。
但關鍵是,這樣的配置應該在應用程序的最高級別組件(根組件)。 這意味着99%的組件應該不能使用 componentWillMount
。
您可能會看到使用componentWillMount
的人啓動AJAX調用來加載組件的數據。 千萬不要這樣作,咱們立刻就會聊到這個。
接下來,更有用的方法是:
最多見的用例: 您的根組件中的應用程序配置。
能夠調用setState:不要。改用默認狀態( default state )。
如今咱們在說話您的組件在那裏,掛載了並準備好使用了。怎麼辦?
這裏是您加載數據的位置。我會讓 Tyler McGinnis 解釋爲何:
You can’t guarantee the AJAX request won’t resolve before the component mounts. If it did, that would mean that you’d be trying to setState on an unmounted component, which not only won’t work, but React will yell at you for. Doing AJAX in componentDidMount will guarantee that there’s a component to update.
您不能保證在組件掛載以前,AJAX請求將 resolve 。若是這樣作,那意味着你會嘗試在一個未掛載的組件上設置StState,這不只不會起做用,反而 React 會對你大喊大叫。在componentDidMount中執行AJAX將保證有一個要更新的組件。
ComponentDidMount
也能夠在作不少你在沒有組件的時候不能作的事情。 下面舉幾個栗子:
繪製您剛剛渲染的<canvas>元素
從元素集合初始化 masonry 網格佈局
增長事件監聽器
基本上,你能夠在這裏作任何剛剛由於沒有 DOM 而不能作的設置,而且能夠獲取你所須要的所有數據。
最多見的用例: 啓動AJAX
調用,以加載組件的數據。
能夠調用setState:是的。
咱們的組成部分作得很好,忽然之間,一大堆新的 props
到達了,使到組件處於混亂狀態。
頗有可能一些由父組件的componentDidMount
加載的數據終於到達,並被傳遞下來。
在咱們的組件對新的 props
進行任何操做以前,將調用componentWillReceiveProps
,並將下一props
做爲參數。
<img alt="componentWillReceiveProps" src="https://cdn-images-1.medium.com/max/800/1*u3rXB0qKor51Qb_R1laPjw.png"
如今,咱們正在處於一個頗有趣的地方,咱們能夠訪問下一個 props
(經過nextProps)和咱們當前的 props
(經過this.props)。
下面這些是咱們在componentWillReceiveProps
中須要作的:
檢查哪些props
會改變(使用componentWillReceiveProps的大警告 - 有時它什麼也沒有改變時被調用; React 只是想作一個檢查)
若是props
會以重要的方式改變props
,就行事。
下面是一個例子。假設咱們在上面提到,咱們有一個 <canvas> 元素。假設咱們根據this.props.percent
繪製一個很好的圓形圖形。
ps` ,若是百分比發生變化,咱們想從新繪製網格。如下是代碼:
componentWillReceiveProps( nextProp ) { if(this.props.percent !== nextProps.percent) { this.setUpCirCle(nextProps.percent) } }
注意:在初始渲染時不調用 componentWillReceiveProps 。
個人意思是在技術上,組件正在接收props
,但沒有任何舊的props
要比較,因此...不算。
最多見的用例:根據特定的props
,更改來觸發狀態(state)轉換。
是否能夠調用setState
: Yes
如今咱們的組件愈來愈緊張了。
咱們有新的props
。典型的React
教條說,當一個組件接收到新的props
或新的state
時,它應該更新。
可是咱們的組件有點焦慮,首先要求許可。
這是咱們所須要的 —— shouldComponentUpdate
方法,以 nextProps
爲第一個參數,nextState
是第二個參數:
shouldComponentUpdate(nextProps, nextState) { return this.props.engagement !== nextProps,engagement || nextState.input !== this.state.input }
shouldComponentUpdate應該老是返回一個布爾值 —— 就像這個問題的答案
--> 「我能夠渲染嗎?」
--> 是的,小組件,你能夠去渲染。
默認狀況下它老是返回true
。
可是,若是您擔憂浪費渲染
其實,shouldComponentUpdate是提升性能的好地方。
我以這種方式寫了一篇關於使用shouldComponentUpdate的文章 - 看看:
How to Benchmark React Components: The Quick and Dirty Guide
在這篇文章中,咱們談論一個有不少fields的表格。問題是,當表從新渲染時,每一個字段也將從新渲染,速度很慢,效率很低。
ShouldComponentUpdate
容許咱們說:只有當所關心的props
的改變的時候才更新!
但請記住,若是您設置並忘記它可能會致使重大問題,由於您的React組件將沒法正常更新。因此謹慎使用。
最多見的用例: 當您的組件 re-render
(從新渲染)時,徹底控制。
是否能夠調用setState
: No
哇,什麼過程如今咱們承諾更新。"但願我在從新渲染以前先作任何事情?" 咱們的組件問。不,咱們說。中止打擾咱們。在整個MuseFind代碼庫中,咱們從不使用componentWillUpdate。在功能上,它基本上與componentWillReceiveProps
相同,除非你不容許調用this.setState
。
若是您正在使用shouldComponentUpdate
而且須要在props
更改時執行某些操做,那麼componentWillUpdate
就會頗有意義。
最多見的用例: 在一個也有shouldComponentUpdate(但不能訪問之前的props
)的組件上使用而不是componentWillReceiveProps
。
是否能夠調用setState
: No
很棒!小組件!
在這裏咱們能夠和componentDidMount
作一樣的事情 : 從新設置咱們的 masonry 佈局,重繪咱們的canvas,等。
等等 - 咱們沒有在componentWillReceiveProps
中重畫咱們的canvas
嗎?
是的咱們沒有作。緣由是:在componentDidUpdate中,你不知道爲何它更新。
所以,若是咱們的組件接收到的canvas
數量超過了與咱們的canvas
相關的props
,咱們不但願每次更新時都會浪費時間重繪canvas
上面。
這並不意味着componentDidUpdate
沒有用。要回到咱們的 masonry 佈局示例,咱們要在DOM自身更新後從新排列網格,因此咱們使用componentDidUpdate
來完成。
componentDidUpdate() { this.createGrid() }
最多見的用例:更新DOM以響應prop
或state
更改。
是否能夠調用setState
: Yes
幾乎結束了~
你的組件將會消失。也許永遠,這很傷心。
在它以前,它詢問你是否有任何最後的請求。
在這裏,您能夠取消任何傳出的網絡請求,或刪除與組件關聯的全部事件監聽器。
基本上,清理任何只涉及到有關的組件的哦事情,
當它走了,它應該徹底消失。
componentWillUnmount() { window.removeEventListen('resize', this,resizeListener) }
最多見的用例:清理組件中殘留的殘留物。
是否能夠調用setState
: No
在理想的世界中,咱們不會使用生命週期方法。咱們全部的渲染問題都將經過state
和 prop
進行控制。
但它事實上並非一個理想的世界,有時您須要更準確地控制組件更新的方式和時間。
謹慎使用這些方法,並當心使用。我但願這篇文章有助於闡明何時和如何使用生命週期方法。