# Component (組件)

&#x20;[官方文檔](https://reactjs.org/docs/react-component.html)

在React Native裡，組件名稱開頭必須是（英文）大寫，所以通常js檔案的名稱也都會用大寫 ，所以通常js檔案的名稱也都會用大寫

我們有兩種資料(data) 來控制一個組件: props 和 state

{% content-ref url="props-and-state" %}
[props-and-state](https://twins-bamboo.gitbook.io/react-native-note/basic/props-and-state)
{% endcontent-ref %}

### Component API

* this.props - 從父組件給予的參數，透過this.props來獲取
* this.state - 此組件內的狀態，透過this.state來獲取
* this.setState(object newState) - 組件想要更新自己的state時，透過this.setState此方法更改state

### Component Lifecycle API <a href="#component-lifecycle-api" id="component-lifecycle-api"></a>

**Mounting Cycle**

* &#x20;constructor() 組件被實例化
  * 此時有的參數為props（由父組件傳遞過來的）
  * 在此初始化state
  * 組件還沒mount，也代表沒有任何 ui 被 render
  * also often used to bind event handlers to the class instance
* &#x20;componentWillMount()
  * 此方法只會在第一次render前被調用。(等於只會被調用一次)
  * 此處 ui 仍然尚未被 render
* &#x20;render()
  * 必須回傳React element做ui的渲染 (或者回傳null，render nothing)
* &#x20;componentDidMount()
  * 此方法只會在第一次render後被調用。(等於只會被調用一次)
  * 此處代表 ui 已經渲染完成
  * 若想直接對特定的ui動作，使用this.refs
  * 通常async api 或者 setTimeout執行延遲和訂閱事件都在此完成
* &#x20;componentWillUnmount()
  * 在組件 unmount 和毀滅之前被調用
  * 在此執行清除的動作，像是使timer、interval等無效、取消網路請求，取消訂閱事件

**Updating Cycle**

* &#x20;componentWillReceiveProps(nextProps)
  * 在mount後收到新的props之前被調用。**代表一開始收到初始的props時此方法不會被調用**
  * 若你收到新的props時，有要更新資料，記得先比對this.props和nextProps是否有不一樣。**因為在react中，此方法不一定會在props有更動的情況下才被調用**
* &#x20;shouldComponentUpdate(nextProps, nextState) return boolean
  * 透過此方法，在props或者state有變動的情況下，控制ui是否重新render
  * 預設為return true
  * 此方法在初次render和forceUpdate時，不會被調用
  * 若要進行優化，請覆寫此方法，並檢查是否props或者state有變動。對這些對象中的每個鍵/值測試。返回false可阻止調用render方法，**參考附1**
  * **若在此處return false，則componentWillUpdate(),render(),componentDidUpdate()都不會被調用到**
* &#x20;componentWillUpdate(nextProps, nextState)
  * 當確定要render ui時，此方法被調用
  * **不能在此處調用setState或者任何會改變到 ui 的操作**
* &#x20;render()
  * 當確定要render ui時，此方法被調用
  * 必須回傳React element做ui的渲染 (或者回傳null，render nothing)
* &#x20;componentDidUpdate()
  * 在重新render之後被調用

###

### 附註

1. 優化 sample code

   ```
   shouldComponentUpdate(nextProps) {
     if(nextProps.item === this.props.item) {
         return false;
     }
     return true;
   }
   ```
2. &#x20; from [crazycodeboy's github](https://github.com/crazycodeboy/RNStudyNotes/tree/master/React%20Native%20%E6%AF%8F%E6%97%A5%E4%B8%80%E5%AD%A6#d23%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E6%80%BB%E7%BB%932016-9-26)

```
生命周期                   调用次数         能否使用 setSate()
getDefaultProps           1(全局调用一次)  否
getInitialState           1              否
componentWillMount        1              是
render                    >=1            否
componentDidMount         1              是
componentWillReceiveProps >=0            是
shouldComponentUpdate     >=0            否
componentWillUpdate       >=0            否
componentDidUpdate        >=0            否
componentWillUnmount      1              否
```

### 參考

下圖和文字來自 [React Native中組件的生命週期](https://www.race604.com/react-native-component-lifecycle/)

&#x20;![](https://bambooooo.gitbooks.io/react-native/content/React%20Native/images/basic/component/component-lifecycle.jpg)

如圖，可以把組件的生命週期大致分為三階段：

* 第一階段(Mounting)：是組件第一次繪製階段，如圖中的上面虛線框內，在這裡完成了組件的加載和初始化
* 第二階段(Updating)：是組件在運行和交互階段，如圖左下角虛線框內，這個階段組件可以處理用戶交互，或者接收事件更新介面
* 第三階段(Unmounting)：是組件卸載消亡的階段，如圖中右下角的虛線框內，這裡做一些組件的清理工作

或參考此圖

![](https://bambooooo.gitbooks.io/react-native/content/React%20Native/images/basic/component/lifecycle.png)
