[TOC]
# Understanding React lifecycle methods
# 理解React生命周期方法
React provides methods to handle the data during the lifecycle of a component. This is very useful when we need to update our application at particular times.
React提供的方法是在組件的生命周期內處理數據。當我們需要在特定時間更新應用程序時,這非常有用。

# 介紹
**所謂的生命周期就是React中定制的一套執行函數的順序**
分為三個階段,每一個階段都有不同的函數執行順序,值得注意的是實例化和銷毀階段執行一次,存在期是可以反復執行的:
1、組件**實例化階段**
(在實例化階段只會執行一次)
?`constructor`
?`componentWillMount`
?`render`
?`componentDidMount`
2、組件**存在階段**
(在組件存在的階段,每重新渲染一次,都會執行一遍)
?`componentWIllReceiveProps`
?`shouldComponentUpdate`(特別注意,如果返回`false`,則不會執行渲染,也會跳過`render`前后的鉤子函數)
?`componnetWillUpdate`
?`render`
?`componentDidUpdate`(渲染之后,可以通過`ref`或者`findDOMNode`,來操作 DOM,當 React 運行在服務端是,不會被調用)
3、組件**銷毀階段**
?`componentWIllUnmount`
?React 組件的生命周期,已經說忘了,那么我們需要看一下,貫穿整個生命周期的`state`和`props`是什么情況。
首先要明白:React 的數據流是單向的。
## 詳解
```js
constructor (構造函數)
```
只有在組件實例化并插入到 DOM 中的時候才會被調用。組件實例 化的過程稱作組件的掛載(mount)。
它在組件初始化時被調用。在這個方法中,你可以設置初始化狀態以及綁定類方法。
```js
componentWillMount()
```
它在`render()`方法之前被調用。**這就是為什么它可以用作去設置組件內部的狀態**,因為它不會觸發組件的再次渲染。但一般來說,**還是推薦在`constructor()`中去初始化狀態**。
```js
render()
```
該方法會在組件被掛載過程中被調用,同時當組件被更新的時候也會被調用,每當組件的狀態 (state)或屬性 (props)改變時,組件的 `render()` 方法都會被調用
這個生命周期方法是必須有的,它返回作為組件輸出的元素。這個方法應該是一個純函數,因此不應該在這個方法中修改組件的狀態。它把屬性和狀態作為輸入并且返回(需要渲染的)元素
```js
componentDidMount()
```
它僅在組件掛載后執行一次。**這是發起異步請求去 API 獲取數據的絕佳時期**。獲取到的數據將被保存在內部組件的狀態中然后在 `render()` 生命 周期方法中展示出來。
```js
componentWillReceiveProps(newProps)
```
這個方法在一個更新生命周期(updatelifecycle) 中被調用。新的屬性會作為它的輸入。因此你可以利用 `this.props` 來對比之后的屬性和之前的屬性,基于對比的結果去實現不同的行為。此外,你可以基于新的屬性 來設置組件的狀態。
```js
shouldComponentUpdate(newProps, newState)
```
每次組件因為狀態或者屬性更改而更新時,它都會被調用。你將在成熟的 React 應用中使用它來進行性能優化。在一個 更新生命周期中,組件及其子組件將根據該方法返回的布爾值( true/false )來決定是否重新渲染。 這樣你可以阻止組件的渲染生命周期(render lifecycle)方法,避免不必要的渲染。**注意在這個生命周期方法中你不能再觸發`setState()`**。
例如 React 中的就提供了一個 `PureComponent` 的類,當我們的組件繼承于它時,組件更新時就會**默認先比較新舊屬性和狀態**,從而決定組件是否更新。值得注意的是,`PureComponent` 進行的是**淺比較**,所以組件狀態或屬性改變時,都需要返回一個新的對象或數組
```js
componentWillUpdate(nextProps, nextState)
```
這個方法是 `render()` 執行之前的最后 一個方法。你已經擁有下一個屬性和狀態,它們可以在這個方法中任由你處置。你可以利用這個方法在渲染之前進行最后的準備。**注意在這個生命周期方法中你不能再觸發`setState()`**。如果你想基于新的屬性計算狀態,你必須利用 `componentWillReceiveProps()`。
```js
componentDidUpdate(prevProps, prevState)
```
這個方法在 `render()` 之后立即調用。你可以用它當成操作 DOM 或者執行更多異步請求的機會。
```js
componentWillUnmount()
```
它會在組件銷毀之前被調用。你可以利用這個生命周期 方法去執行任何清理任務。
```js
componentDidCatch(error, info)
```
錯誤處理,它在 React 16 中引入,用來 捕獲組件的錯誤。舉例來說,在你的應用中展示樣本數據本來是沒問題的。但是可能會有列表的本地狀態被意外設置成 `null` 的情況發生(例如從外部 API 獲取列表失敗時,你把本 地狀態設置為空了)。然后它就不能像之前一樣去過濾(filter)和映射(map)這個列表,使用真實的 API因為它不是一個空列表(`[]`)而是 `null`。這時組件就會崩潰,然后整個應用就會掛掉。現在你可以用 `componentDidCatch()` 來捕獲錯誤,將它存在本地的狀態中,然后向用戶展示一條信息,說明應用發生了錯誤。
> 注意??:新版本的中的生命周期有所變動
# 參考
[圖解 ES6 中的 React 生命周期](https://juejin.im/post/5a062fb551882535cd4a4ce3)
[setState詳解](https://blog.csdn.net/sysuzhyupeng/article/details/63250741)
https://blog.csdn.net/Donspeng/article/details/76662664
https://blog.csdn.net/ytongc/article/details/79182161