Reactのライフサイクルとは?初心者向けに基本の流れを解説
生徒
「Reactのライフサイクルって何ですか?なんだか難しそうです…」
先生
「いい質問ですね。Reactのライフサイクルは、コンポーネントが画面に表示されてから消えるまでの『一連の流れ』のことです。」
生徒
「コンポーネントが生まれてから消えるまでの流れ…ですか?」
先生
「そうです。人間で言えば『誕生 → 成長 → 引退』のようなものですね。Reactでも同じように、コンポーネントが作られて、更新されて、最後に消えるまでにいくつかの段階があります。」
生徒
「なるほど!それぞれの段階では何が起きるんですか?」
先生
「それでは、Reactコンポーネントのライフサイクルの流れを詳しく見ていきましょう。」
1. Reactのライフサイクルとは?
React(リアクト)のライフサイクルとは、コンポーネントが「生成される(マウント)」「更新される(アップデート)」「削除される(アンマウント)」までの流れを指します。
Reactでは、この流れに合わせて特定のタイミングで処理を実行することができます。たとえば、データを取得したり、タイマーを設定したり、後片付けをしたりすることが可能です。
Reactのライフサイクルを理解することで、アプリの動きをコントロールしやすくなり、不要な処理を減らしてパフォーマンスを向上させることができます。
2. コンポーネントの3つのライフサイクル段階
Reactのコンポーネントには、主に次の3つの段階があります。
- マウント(Mount):コンポーネントが画面に初めて表示されるとき
- アップデート(Update):コンポーネントが再描画されるとき(状態やプロパティが変化)
- アンマウント(Unmount):コンポーネントが画面から削除されるとき
これらの段階を理解しておくことで、「いつ」「どんな処理」を書けばよいかが分かるようになります。
3. useEffectでライフサイクルを管理する
Reactの関数コンポーネントでは、useEffectというフックを使うことでライフサイクルの流れを扱うことができます。
まずは、基本的なサンプルを見てみましょう。
import React, { useState, useEffect } from "react";
function LifeCycleExample() {
const [count, setCount] = useState(0);
// マウント時に実行される
useEffect(() => {
console.log("コンポーネントがマウントされました!");
// アンマウント時に実行される処理
return () => {
console.log("コンポーネントがアンマウントされました!");
};
}, []);
// countが変わるたびに実行される
useEffect(() => {
console.log("countが更新されました:", count);
}, [count]);
return (
<div>
<h1>カウント: {count}</h1>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
}
export default LifeCycleExample;
useEffectの第2引数([])は「依存配列」と呼ばれます。
この中に変数を入れると、その値が変化したときにだけ再実行されます。空の配列にすると、最初の1回だけ実行されます。
4. ライフサイクルの流れを図でイメージしよう
Reactのライフサイクルは、次のような流れで進みます。
① コンポーネントが作られる(マウント)
↓
② 状態やデータが変化して再描画される(アップデート)
↓
③ コンポーネントが削除される(アンマウント)
これを人間の一生にたとえると、次のようになります。
- マウント=誕生(コンポーネントが画面に登場)
- アップデート=成長(データが更新される)
- アンマウント=引退(コンポーネントが消える)
このように考えると、ライフサイクルはとても理解しやすくなります。
5. 実践:ライフサイクルを使ってタイマーを作る
次は、ライフサイクルを活かした実践例です。画面に秒数を表示し、コンポーネントが削除されるときにタイマーを止めます。
import React, { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// マウント時にタイマー開始
const timer = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
// アンマウント時にタイマーを止める
return () => clearInterval(timer);
}, []);
return (
<div>
<h2>経過時間: {seconds}秒</h2>
</div>
);
}
export default Timer;
このように、useEffectを使うことで「開始時の処理」と「終了時の処理」を簡単にまとめることができます。
Reactアプリの中では、API通信・イベントリスナー・アニメーションの制御などでもこの仕組みが使われます。
6. ライフサイクルを理解するメリット
Reactのライフサイクルを理解することで、次のようなメリットがあります。
- アプリの動きを意図通りにコントロールできる
- 不要な処理を減らし、パフォーマンスを向上できる
- API通信やイベント登録のタイミングを正しく管理できる
- エラーやメモリリーク(不要なメモリ使用)を防げる
Reactのライフサイクルは、初心者がつまずきやすい部分でもありますが、一度理解すればとても便利な考え方です。
Reactのアプリ開発において、データの管理や描画の仕組みを深く理解するための第一歩となるでしょう。
まとめ
Reactのライフサイクルについて、マウント、アップデート、アンマウントという3つの主要なフェーズを軸に解説してきました。モダンなReact開発においては、クラスコンポーネント時代の複雑なライフサイクルメソッドを個別に覚える必要はなく、useEffectという強力なフック一つでこれらを直感的に制御できるようになっています。
特に重要なポイントは、「副作用(Side Effects)をいつ実行し、いつクリーンアップするか」という視点を持つことです。例えば、外部データのフェッチはマウント時に行い、イベントリスナーやタイマーの解除はアンマウント時に行うといった役割分担が、アプリケーションの堅牢性を高めます。
さらに一歩進んだReactライフサイクルの応用
ここでは、学んだライフサイクルの知識を活かして、実務でもよく使われる「ウィンドウのリサイズ検知」を行うコンポーネントを作成してみましょう。このコードでは、マウント時にイベントを登録し、アンマウント時に解除するというライフサイクルの基本が詰まいています。
import React, { useState, useEffect } from "react";
function WindowSizeMonitor() {
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
useEffect(() => {
// 画面サイズが変更された時に実行する関数
const handleResize = () => {
setWindowWidth(window.innerWidth);
console.log("サイズが変更されました:", window.innerWidth);
};
// マウント時にイベントリスナーを登録
window.addEventListener("resize", handleResize);
// アンマウント時にイベントリスナーを解除(クリーンアップ関数)
return () => {
window.removeEventListener("resize", handleResize);
console.log("イベントリスナーが削除されました");
};
}, []); // 依存配列が空なのでマウント・アンマウント時のみ動作
return (
<div className="p-4 border rounded bg-light">
<h3 className="fs-6">現在のブラウザ横幅</h3>
<p className="display-4">{windowWidth}px</p>
<p className="text-muted">ブラウザの端をドラッグしてサイズを変えてみてください。</p>
</div>
);
}
export default WindowSizeMonitor;
React開発で意識すべきベストプラクティス
ライフサイクルを扱う上で、以下の3点は常に意識しておくと良いでしょう。
- 依存配列の適切な管理:
useEffectの第二引数を省略すると、毎レンダリングごとに実行されてしまいパフォーマンスが低下します。必要な値だけを配列に入れましょう。 - クリーンアップの徹底:
setIntervalや外部ライブラリのインスタンス化など、メモリを消費するものは必ずreturn内で後片付けをします。 - 無限ループに注意:
useEffectの中で状態(State)を更新し、その状態を依存配列に入れていると、更新が更新を呼ぶ無限ループに陥ることがあります。
Reactのライフサイクルをマスターすることは、単に表示を切り替えるだけでなく、効率的でメモリ効率の良いプロフェッショナルなアプリケーションを構築するための必須スキルです。まずは簡単な console.log で「今どのフェーズにいるのか」を確認しながら、コードを書いて体感していくのが上達の近道です。
生徒
「先生、ありがとうございました!ライフサイクルって聞くと難しそうでしたけど、要するに『画面に出るとき、変わるとき、消えるとき』に何をさせるかってことなんですね。」
先生
「その通りです!よく理解できましたね。特に、関数コンポーネントでは useEffect さえ使いこなせれば、ほとんどのケースに対応できるのが嬉しいところです。」
生徒
「さっきのタイマーやリサイズ検知のコードを見て思ったんですけど、最後の return で後片付けをするのがすごく大事なんですね。もし忘れたらどうなるんですか?」
先生
「良いところに気が付きましたね。もし後片付けを忘れると、コンポーネントが画面から消えた後も、裏側でタイマーが動き続けたり、ブラウザが一生懸命イベントを監視し続けたりします。これが『メモリリーク』の原因になって、アプリがどんどん重くなってしまうんです。」
生徒
「それは怖いですね…。キャンプ場と同じで『来た時よりも美しく』、終わったら片付けるのが鉄則ですね!あと、依存配列の [] を空にするのと、値を入れるのの違いも、なんとなく分かってきました。」
先生
「素晴らしい例えです!空の配列 [] は『最初の一回だけやる』という合図。中に変数を入れると『その変数が変わった時だけやり直す』という合図になります。これらを使い分けられるようになると、無駄な再描画を防いで、サクサク動くWebアプリが作れるようになりますよ。」
生徒
「ありがとうございます!次は、実際にAPIからデータを取得する処理をライフサイクルの中で書いてみたいと思います。マウントされた瞬間に最新のニュースを取ってくる、みたいな!」
先生
「いいですね、その意気です。実際の開発ではそれが一番よく使われるパターンですからね。ライフサイクルの基本が身についていれば、非同期処理の管理もきっとスムーズにマスターできますよ。頑張りましょう!」