Reactのコンポーネントライフサイクルを知ろう

#目次

* [概要](#概要)
* [Reactのコンポーネントライフサイクルとは](#reactのコンポーネントライフサイクルとは)
* [ライフサイクルメソッドの説明](#ライフサイクルメソッドの説明)
* [まとめ](#まとめ)


#概要

この記事は、現在Reactを勉強中である私が**Reactのライフサイクル**についての理解を深めるためにまとめたものです。私と同じようにReactを勉強中の人にとってこの記事が手助けとなるようであれば幸いです。
Reactの基礎の基礎については[別の記事](https://qiita.com/jima-r20/items/48220ec1980535280a66)にまとめています。本記事は最低限必要な基礎を既に学習済みの方向けの内容となっています。


#Reactのコンポーネントライフサイクルとは

Reactのコンポーネントには**ライフサイクル**というものが存在します。私が色々と調べている中でわかりやすいと感じた例が「**日の出から日の入り**」です。
コンポーネントのライフサイクルは**Mounting**、**Updating**、**Unmounting**という３つの状態を遷移しています。
この３つの状態と上記の例を対応付けると、以下の表のようになります。

|    状態         | 時間帯   |  説明  |
|:--------------:|:-------:|:------|
| **Mounting**   | 日の出前  | コンポーネントのインスタンスが作成され、**DOMに挿入されるとき**。**レンダリングの準備期間**。 |
| **Updating**   | 日中     | propsやstateの変更によりコンポーネントが**再レンダーされるとき**。**ユーザが操作可能な期間** |
| **Unmounting** | 日の入り後 | コンポーネントが**DOMから削除されるとき**。 |


![image_of_lifecycle.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622836/ea5556c6-76f1-fbab-761e-0785add3884d.png)


コンポーネントのライフサイクルでは、各状態に応じて仕様できる**ライフサイクルメソッド**というものが用意されています。
ライフサイクルメソッドの詳しい説明については[こちら](#ライフサイクルメソッド)をご覧ください。
(これらはクラスコンポーネントで使用できるメソッドですが、React v16.8でHooksの`useEffect()`を用いて関数コンポーネントでも一部代用できるようになりました。)
###Mounting
* `constructor ()`
* `static getDrivedStateFromProps ()`
* `render ()`
* `componentDidMount ()`

###Updating
* `getDrivedStateFromProps ()`
* `shouldComponentUpdate ()`
* `render ()`
* `getSnapshotBeforeUpdate ()`
* `componentDidUpdate ()`

###Unmounting
* `componentWillUnmount ()`


![component_lifecycle.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622836/ed970f6c-f249-0541-dc82-779b7843732b.png)



#ライフサイクルメソッドの説明
ここでは、先ほど紹介したライフサイクルメソッドを使用頻度の多い順に説明をします。
###よく使うライフサイクルメソッド
####`render()`
使用できる状態： **Mounting / Updating**

* クラスコンポーネントで**必ず**定義しなければならないメソッド
* propsやstateが更新されるたびに呼ばれる
* 純粋関数である必要がある：render()内でpropsやstateなどを直接操作してはいけない
* 返す要素は単一：要素全体を一つのタグで囲む(`<div>`や`<React.Fragment>`など)

####`constructor()`
使用できる状態： **Mounting**

* Mounting時に**一番最初に呼ばれる**メソッド
* `React.Component`のサブクラスで実装するときには`super(props)`を呼び出す必要がある
* `this.state`を初期化するときに使用
* イベントハンドラをインスタンスにバインドするときに使用

####`componentDidMount()`
使用できる状態： **Mounting**

* コンポーネントが**マウントされた直後に一度だけ**呼び出される（１度目の`render()`後）
* DOMに関する初期化処理をしたいときに使用(直接DOM操作などはしないこと)
* ネットワークへのリクエストなどを行うときに使用
* `setTimeout()`などはここで行う

####`componentDidUpdate()`
使用できる状態： **Updating**

* コンポーネントの**更新が行われたタイミング**で呼び出される
* 第一引数にprevProps(直前のprops)、第二引数にprevState(直前のstate)を受け取る
* 第三引数にsnapshotをとる場合もある（後述の`getSnapshotBeforeUpdate()`の返り値)

####`componentWillUnmount()`
使用できる状態： **Unmounting**

* 現在の**コンポーネントが破棄(アンマウント)される直前**で呼ばれるメソッド
* タイマーの無効化、ネットワークへのリクエストのキャンセルなどを行う
* 必要ない設定を破棄することでメモリを開放できる
* この後に`render()`が呼ばれることはない

###まれに使うライフサイクルメソッド
####`static getDrivedStateFromProps()`
使用できる状態： **Mounting / Updating**

* propsの値によってstateに更新があるかチェックするメソッド
* Mounting時は`render()`の直前、Updating時は一番最初に呼ばれる
* 第一引数にprops、第二引数にstate
* stateがpropsに依存するというなまれな場合に使用
* 更新があれば更新後の`state`、ない場合は`null`を返す

####`shouldComponentUpdate()`
使用できる状態： **Updating**

* **新たなstateやpropsを受け取った場合**に`render()`の直前で呼び出されるメソッド
* 第一引数にnextProps(更新後のprops)、第二引数にnextState(更新後のstate)
* `true`または`false`を返す
* デフォルトは`true`を返し再レンダリングをするが、`false`が返った場合は更新がスキップされる

####`getSnapshotBeforeUpdate()`
使用できる状態： **Updating**

* `render()`後`componentDidUpdate()`が呼び出される直前で呼び出されるメソッド
* コンポーネントが変更される可能性があるとき、**スクロール位置などの情報を取得することができる**
* 返り値は`componentDidUpdate()`の第三引数に渡される


#まとめ
今回はReactのコンポーネントライフサイクルについてまとめてみました。
Reactを扱う上でよく使う`render()`メソッドもライフサイクルメソッドの一つであるということを抑えておきましょう。
それ以外にも`constructor()`や`componentDidMount()`などよく登場するメソッドについては理解しておくと良いかと思います。

#参考資料

* [React公式サイト](https://ja.reactjs.org/docs/react-component.html#the-component-lifecycle)
* [【Reactの設計を学ぶ】ライフサイクルを知ろう](https://code-ship-blog.wemotion.co.jp/technology/%E3%80%90react%E3%81%AE%E8%A8%AD%E8%A8%88%E3%82%92%E5%AD%A6%E3%81%B6%E3%80%91%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%82%92%E7%9F%A5%E3%82%8D%E3%81%86/)
* [React(v16.4) コンポーネントライフサイクルメソッドまとめ](https://qiita.com/Julia0709/items/3c3fc8d29fd2e56ed7a9)
* [ざっくり React チュートリアル](https://qiita.com/pullphone/items/efcaee59cf2a5725c61d#%E3%81%BE%E3%81%A8%E3%82%81)
* [React Component Lifecycle](https://dev.to/jaylcaetano/react-component-lifecycle-2npl)