Reactのライフサイクル、useState、useEffectについて理解する
はじめに
この記事では、私がuseStateとuseEffectについて学習した内容を、自分の理解のためにも、また他の方の参考になればと思い、まとめています。
初学者はもちろん、普段Reactを使用している方にもなにか気付きがあれば幸いです。
もし、間違って認識していることがあればコメントいただけると嬉しいです。
ライフサイクルについて
仮想DOMについて
そもそもDOMとは、Document Object Modelの略で、HTMLやXMLのようなマークアップ言語で書かれた文書の構造のことです。
JavascriptやjQueryなどのフレームワークでは、情報をもとにDOMを再構築していましたが、再構築を待って画面を描画していると遅くなることが課題としてありました。
Reactにおいては、仮想DOM(プログラム的に作成された仮のDOM)を構築して、仮想DOMをもとにDOMを更新することを行っています。
仮想DOMを使用することで、変更前と変更後の差分を検知して、差分のみをDOMに同期させることができるため、画面描画の高速化を実現しています。
仮想DOMについて詳しくは、下記の記事がわかりやすいです。
Reactのレンダリングについて
画面描画までの上記を踏まえて、Reactでは下記の流れが行われます。
- レンダーをトリガー
- 画面に表示するきっかけをキャッチする
- タイミングは初回 or 画面の更新時
- コンポーネントのレンダリング
- 初回レンダリング時はルートコンポーネントを呼び出す
- 更新時は、仮想DOMの差分を見て、更新するかどうかの判定を行っている
- DOMの更新
- 実際に差分があった場合にDOMの更新を行う
レンダリングについては、下記の記事がわかりやすいです。
コンポーネントのライフサイクル
ライフサイクルとは、コンポーネントがマウントされたとき、アンマウントされたとき、更新されたときなど、コンポーネントの状態の変化の流れのことです。
Reactのライフサイクルは以下の3つのフェーズに分類できます。
- マウント
- 初回のレンダリング時
- 更新
- コンポーネントの再レンダリング時
- アンマウント
- コンポーネントがDOMから削除される時
useEffectとは
コンポーネントを外部システムと同期させるためのReactフックです。
外部システムとの同期の例としては、サーバーとの接続を確立することや、コンポーネントが画面に表示された際に分析用のログを送信したりすることなどです。
エフェクトとは、特定のイベントによってではなく、レンダー自体によって引き起こされる副作用を指定するためのものです。
補足
Reactコンポーネント内の役割は他にも以下の2種類が存在しています。
レンダーコード
コンポーネントのトップレベルにあるものです。ロジックは持たずに、画面に表示したいJSXを返す場所です。
イベントハンドラ
特定のユーザーアクション(ボタンのクリックや入力)によって引き起こされてプログラムの状態を変更する副作用が含まれています。
実装サンプル
import { useEffect } from 'react';
import { createConnection } from './chat.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
引数
- setup
- ロジックが記載された関数。オプションでクリーンアップ関数を返すことができる。
- マウント時にsetup関数を実行する
- アンマウント後に、クリーンアップ関数を実行する
- 依存配列(dependencis)が変更された再レンダー時
- まず、古い値を使用してクリーンアップ関数が実行される
- 次に新しい値を使ってsetup関数が実行される
- 依存配列(dependencis)が変更された再レンダー時
- dependencis(省略可能)
- コード内で参照されるリアクティブな値のリスト
- 最初のレンダー時、指定された値が変わった後の再レンダー後に実行される
- 空の配列を渡した場合は、初回レンダリング後のみ実行される
- 省略した場合は、コンポーネントの毎回のレンダー後に実行される
- コード内で参照されるリアクティブな値のリスト
useStateとは
コンポーネントにstate変数を追加するためのReactフックです。
実装サンプル
import { useState } from 'react';
function MyComponent() {
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [todos, setTodos] = useState(() => createTodos());
// ...
}
引数
- initialState
- stateの初期値
- 初回レンダリング後は無視される
- 関数を渡した場合は、コンポーネントを呼び出すときに初期化関数を呼び出し、その返り値を初期stateとして保存する
返り値
- 現在のstate。初回レンダリング中は、initialStateと同じ値になる
- stateを別の値に更新し、再レンダーをトリガーするset関数
参考資料
Discussion