はじめに
この記事ではReactのライフサイクルについて紹介します。
ライフサイクルとライフサイクルメソッドは開発において設計を理解するためにも非常に重要です。
ここで一度概略を掴んでおくと、自分で必要になった時に理解が進むと思います。
イメージしにくいかもしれませんが、ぜひ通読してみて下さい。
対象読者は以下のことが理解できている方です。
- JSXを使った簡単な画面のレンダリング
- stateやpropsの使い方
- コンポーネントのimportやexportの仕組み
全くReactを知らない方は、まずこちらを読んでみてください。
公式のリファレンスはこちらです。
目次
Reactのライフサイクルとは
Reactのコンポーネントにはライフサイクル(lifecycle)と呼ばれる時間の流れがあります。
イメージとしては日が昇り、日中に活動し、夜になり就寝するという感じです。
このライフサイクルは3つの状態を遷移します。
それはMounting・Updateing・Unmoutingの3つです。
具体的には以下のようなものです。
タイミングと内容 | 時間帯に例えると… | |
---|---|---|
Mounting | コンポーネントがユーザーにレンダリングされるまでの仕込みの期間 | 日の出 |
Updating | コンポーネントがユーザに表示されており、ユーザーが操作できる期間 | 日中 |
Unmouting | 他のコンポーネントに切り替え前に現在表示されているコンポーネントを破棄するための期間 | 日暮れ |
それぞれの段階にはその時に使えるものが定義されています。
次に紹介します。
ライフサイクルメソッドとは
上で説明したライフサイクルにはそれに付随したライフサイクルメソッドというものがあります。
これらのメソッドはライフサイクルに合わせて順番に呼ばれます。
ただし、これらはクラスベースのコンポーネントでしか使用できないことに注意してください。
(補足):関数ベースコンポーネントとクラスベースコンポーネント
// function based component
import React from 'react';
const welcome = (props) => {
return <h1>Hello, {props.name}</h1>
}
// class based component
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
先程、ライフサイクルメソッドはクラスベースコンポーネントでしか使用できないと説明しましたが、関数ベースのコンポーネントでは新機能があり、useEffect()というフックで一部代用できます。
これは後に説明するcomponentDidMount, componentDidUpdate, componentWillUnmountが3つ合わさったようなものです。
興味がある方は以下を参照してください。
React Document:副作用フックの利用法
ライフサイクルメソッドの流れ
ライフサイクルメソッドには呼ばれる順番とその役割があります。
Mounting・Updateing・Unmouting時によばれる主なものには以下があります。
Mounting
constructor()
Mounting時に一番最初に呼ばれるメソッドです。
JSXでは使われることがほとんどないため、見かけることもまれです。
super(props)を呼び、更新がする必要性があれば更新できます。
getDerivedFromProps()
このメソッドだけはstatic
です。
render()が呼ばれる前にstateの更新があるかどうかを確認します。
もしあれば更新後のstate
、無ければnull
を返します。
render()
このメソッドだけはコンポーネントで必須です。
ReactがJSXコードを評価して、仮想DOMを構築します。
componentDidMount()
このメソッドは重要なライフサイクルメソッドの一つです。
クラスベースのコンポーネントを操作する時に非常に多く使用します。
1回目のrender()が呼ばれた時に1度だけ呼ばれ、ネットワークへのリクエストなどはこのメソッド内で行います。
Update
getDerivedStateFromProps()
Update時に一番最初に呼ばれるメソッドです。
コンポーネントのstateを初期化します。
ただし、使用頻度は低いです。
shouldComponentUpdate()
コンポーネントの評価と再レンダリングを継続するかどうかを決定します。
つまり更新をここでキャンセル出来ます。
ただし、更新をブロックするとコンポーネントが破損する可能性があるので慎重に使う必要があります。
render()
上記と同様にレンダリングするメソッドです。
これも必須のメソッドです。
getSnapshotBeforeUpdate()
更新が発生する直前のスクロールを位置を記憶して、提供するような使い方が出来ます。
このメソッドも使用頻度は低いです。
componentDidUpdate()
更新が完了した際に呼ばれるメソッドです。
HTTPリクエストを作成できますが、無限ループにならないように注意する必要があります。
Unmouting
componentWillUnmount()
コンポーネントがUnmountされるときに呼ばれるメソッドです。
アニメーションなどを設定した場合はここで破棄します。
それにより次に新しいコンポーネントのサイクルが始まった際にも、その分のリソースを削減できます。
Mounting時のライフサイクルメソッドの実行
メソッドの呼ばれる順番とそれぞれの役割について説明しました。
最後にMounting時のライフサイクルメソッドが呼ばれる過程を実際にコンソールに出力させて確認してみます。
以下のコードをReactのApp.jsに記述し、実際にコンパイルしてみます。
import React, { Component } from 'react';
class App extends Component {
// constructor
constructor(props) {
super(props);
console.log('[App.js] constructor');
}
state = {
persons: [
{ name: 'Ayano', age: 22 },
{ name: 'Yuka', age: 21 },
{ name: 'Ayaka', age: 21 }
],
};
// getDerivedStateFromProps
static getDerivedStateFromProps(props, state) {
console.log('[App.js] getDerivedStateFromProps', props);
return state;
}
// componentDidMount
componentDidMount() {
console.log('[App.js] componentDidMount');
}
// render
render() {
console.log('[App.js] render');
return (
<div>
<h1>This is App.js</h1>
<p>React lifecycle method description</p>
<ul>
<li>{this.state.persons[0].name}</li>
<li>{this.state.persons[1].name}</li>
<li>{this.state.persons[2].name}</li>
</ul>
</div>
);
}
}
export default App;
すると以下のようにレンダリングされると同時に、呼ばれたメソッド名もコンソールに出力されます。
Consoleにcontructor → getDerivedStateFromProps → render → componentDidMount
の順に出力されています。
今回はこれらのメソッドに機能を追加しているわけでないですが、実際にライフサイクルが存在することは確認できました。
まとめ
ライフサイクルとライフサイクルメソッドについて紹介しました。
実際に使う時にならないとなかなかイメージが湧きづらいかもしれませんが、概要をつかめればこれからの開発時に役立つはずです。
これからReactを学んでみたい方の一助になれば幸いです。
React.jsに関する他の記事を見る↓↓
参考文献・URL
stateとライフサイクル
https://ja.reactjs.org/docs/state-and-lifecycle.html#___gatsby
React(v16.4) コンポーネントライフサイクルメソッドまとめ
https://qiita.com/Julia0709/items/3c3fc8d29fd2e56ed7a9
React コンポーネントのライフサイクルとメソッドの役割について
https://qiita.com/koseki/items/432cd54b37cf44865dbd
What does Side effects mean in React?
https://www.reddit.com/r/reactjs/comments/8avfej/what_does_side_effects_mean_in_react/