i-Vinci TechBlog
株式会社i-Vinciの技術ブログ

React のライフサイクルについて

こんにちは!i-Vinci Sです。
i-VinciにはTechLeadチームという技術について研究をするチームが存在します。
主に「技術を追求したい!!」と熱い気持ちを持った社員が集い、日々研究に明け暮れています。
今回は熱い気持ちを滾らせながら日々TechLead活動を行っているMさんが作成した資料「Reactのライフサイクルについて」をブログ記事化してみました。

目次

  1. はじめに
  2. Reactの状態の種類
  3. 実際に見てみる
  4. まとめ

はじめに

ReactとはJavaScriptのライブラリの1つで、ユーザーインターフェースを構築する際に使用します。
Reactでは画面の構成要素を部品であるコンポーネントの集まりで構成しており、コンポーネントの中にはstateと呼ばれるアプリケーションの状態を表すデータを保持しています。
状態によってコンポーネントをどのように画面へレンダリング(描画)するのか指定します。
今回はReactの状態毎にコンポーネントが生成、更新、削除されるまでの流れ(ライフサイクル)を紹介していきます。

Reactの状態(state)の種類

Reactのコンポーネントにはライフサイクルと呼ばれる時間の流れがあり、「Mounting」、「Updating」、「Unmounting」の3つの状態を遷移します。それぞれのライフサイクルに状態が変わるタイミングで呼ばれるメソッド(=ライフサイクルメソッド)が存在しており、これによりコンポーネントの細かなレンダリングが可能になっています。今回の記事では以下の3つが登場します。

ライフサイクル (状態)ライフサイクルメソッド
Mounting (DOM として描画されるとき) componentDidMount
Updating (DOM が再描画されるとき)componentDidUpdate
Unmounting (DOM が削除されるとき)componentWillUnmount

実際に見てみる

それでは実際にコードと表示画面を見ながらライフサイクルを見ていきましょう!

ライフサイクルによる表示の変化

まずはライフサイクルによりどのように表示が変わるのかを見ていきます。
状態が変更された場合に実行したい処理は、useEffect 関数を使用して実行します。

useEffect(() => {
  console.log('componentDidMount'); // Mounting時に実行される処理

  return () => {
    console.log('componentWillUnmount'); // Unmounting時に実行される処理
  };
}, []); // 第2引数が空配列の場合、初回Mounting時のみ実行される

useEffect(() => {
  if (count === 0) return; // 初回Mounting時にも処理されるためスキップ
  console.log('componentDidUpdate'); // Updatingに実行される処理
}, [count]); // 第2引数に値が設定されている場合、値が更新されたときに更新処理が実行される

初回表示(Mounting)

Lifecycle.js componentDidMount

ログに'componentDidMount'が表示されているので、ライフサイクルの状態が「Mounting」だと分かります。

次に「countUp」を押してライフサイクルの状態を更新してみます。

"count up"ボタン押下(Updating)

Lifecycle.js componentDidUpdate  

数字の0から1に変化しており、ログに'componentDidUpdate'が表示されているので、ライフサイクルの状態が「Updating」されたことが分かります。

次はFetchを押してみます。そうすると別のコンポーネントに移動することにより、現在のコンポーネントが削除されることになり、ライフサイクルの状態の「Unmounting」が確認できます。

"Fetch.js"にページ遷移(Unmounting)

Lifecycle.js componentWillUnmount

ログに'componentWillUnmount'と表示されているので、コンポーネントが削除されたことが確認できます。こちらで一通り状態によって処理がどの様に動くかを確認することが出来ました。

非同期処理

またFetchページではMounting時に非同期処理を呼び出し、レスポンスが帰ってきたら State を更新し、再レンダリングを行って非同期で取得したデータを反映させています。

useEffect(() => {
  fetch('https://jsonplaceholder.typicode.com/users')
    .then((response) => response.json())
    .then((data) => setUsers(data)); // レスポンスが返却されたらstateを更新
}, []); // Mounting時のみ実行

"Fetch.js"

Lifecycle.js componentWillUnmount

タイマーのセット

そして最後にTimer画面に移動すると、こちらではMounting時にタイマーをセットし、1 秒ごとにステートを更新し再レンダリングしています。
これによりフロントだけでも時間の表示が可能となります。
setIntervalはグローバル空間で処理されるため、アンマウントした場合でも処理が残り続けます。
そのため、アンマウント時に clearInterval で明示的にリソースを開放する必要があります。
clearInterval 処理をコメントアウトした場合に、Timer 画面から別画面に遷移してもコンソールログが出力され続けることが確認できます。

useEffect(() => {
  console.log('setInterval');
  const interval = setInterval(() => {
    console.log('updateTimer');
    setTimer(new Date()); // ステートを更新
  }, 1000);

  return () => {
    console.log('clearInterval');
    clearInterval(interval); // Unmounting時に呼び出し
  }
}, []); // Mounting時のみ実行

"初回表示, 時間経過(Mounting, Updating)

Timer.js componentDidMount,componentDidUpdate

"Lifecycle"ページに画面遷移(Unmounting)

Timer.js componentWillUnmount

ログに'clearInterval'が表示されて、以降'updateTimer'が表示されていないので、タイマー処理が終了されたことが確認できます。

まとめ

Reactのライフサイクルについてソースコードを元にご紹介しました。
今後も定期的にTechLeadから共有された情報を元にブログ記事を作成していく予定ですので、お楽しみに!