マウント・更新・アンマウントの3つの段階を理解しよう
生徒
「Reactのライフサイクルってよく聞くけど、何のことですか?」
先生
「Reactのライフサイクルとは、コンポーネントが画面に現れてから消えるまでの一連の流れのことなんです。」
生徒
「なるほど!でも、それってどんな流れなんですか?」
先生
「大きく分けて3つの段階があります。『マウント』『更新』『アンマウント』です。」
生徒
「3つの段階?なんだか難しそうですね…」
先生
「大丈夫です!人の一生にたとえるとわかりやすいですよ。『生まれる』『成長する』『去る』のような流れです。これをReactでの動きとして順番に見ていきましょう。」
1. マウント(Mount)とは?コンポーネントが生まれる瞬間
「マウント」とは、Reactコンポーネントが画面上に初めて表示されるタイミングのことです。
たとえば、アプリを開いたときにボタンや文字が最初に表示される瞬間が「マウント」です。
この段階では、コンポーネントの初期設定を行ったり、外部のAPI(別のサービスからデータを取得する仕組み)を呼び出したりすることがよくあります。
Reactでは、useEffectフックを使ってこのマウント時の処理を行います。
import React, { useEffect } from "react";
function MountExample() {
useEffect(() => {
console.log("コンポーネントがマウントされました!");
}, []);
return <h1>こんにちは!Reactの世界へようこそ!</h1>;
}
export default MountExample;
このように、空の配列 [] を指定すると「最初の1回だけ」実行されます。つまり、コンポーネントが“生まれた瞬間”の処理を書けるということです。
2. 更新(Update)とは?コンポーネントが変化する瞬間
次の段階は「更新(アップデート)」です。これは、コンポーネントの中のデータ(stateやprops)が変わったときに起こります。
たとえば、ボタンを押したときにカウントの数字が増えるような動きがこれにあたります。
import React, { useState, useEffect } from "react";
function UpdateExample() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("カウントが更新されました! 現在の値:", count);
}, [count]);
return (
<div>
<h2>現在のカウント: {count}</h2>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
}
export default UpdateExample;
useEffectの第二引数に[count]を指定することで、countが変化したときだけ処理を実行できます。
これがReactにおける「更新(アップデート)」のタイミングです。
人の成長にたとえると、「新しい経験をして少しずつ変化していく」段階だと思ってください。
3. アンマウント(Unmount)とは?コンポーネントが消える瞬間
最後の段階は「アンマウント」です。これは、コンポーネントが画面から消えるタイミングのことです。
ページを切り替えたり、ある要素が非表示になったときに実行されます。
アンマウントのときには、不要になった処理を「後片付け(クリーンアップ)」します。たとえば、タイマーを止めたり、イベントを解除したりする場面です。
import React, { useEffect } from "react";
function UnmountExample() {
useEffect(() => {
console.log("マウントされました!");
// コンポーネントが削除されるときに呼ばれる関数
return () => {
console.log("アンマウントされました!");
};
}, []);
return <h2>このメッセージは一時的に表示されます。</h2>;
}
export default UnmountExample;
このreturn () => { ... }の部分が、アンマウント時の処理を記述する場所です。
まるで「部屋を出る前に電気を消す」ような、後片付けのタイミングですね。
4. 3つの段階をつなげて理解しよう
ここまでの内容をまとめると、Reactのコンポーネントは次のようなサイクルで動いています。
① マウント(生まれる) → コンポーネントが画面に表示される
② 更新(成長する) → 状態やデータが変わり再描画される
③ アンマウント(消える) → コンポーネントが削除される
これを人間の一生にたとえると、「誕生 → 成長 → 引退」です。
Reactでは、この流れに合わせて必要な処理を書き分けることで、アプリの動きを正確に制御できます。
5. 3つの段階を体験できるサンプル
最後に、マウント・更新・アンマウントを1つのサンプルで体験してみましょう。
import React, { useState, useEffect } from "react";
function LifeCycleDemo() {
const [show, setShow] = useState(true);
const [count, setCount] = useState(0);
useEffect(() => {
console.log("マウントされました!");
return () => {
console.log("アンマウントされました!");
};
}, []);
useEffect(() => {
console.log("カウントが更新されました!", count);
}, [count]);
return (
<div>
{show && (
<div>
<h2>ライフサイクルの学習中!</h2>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
)}
<button onClick={() => setShow(!show)}>
{show ? "コンポーネントを削除" : "コンポーネントを表示"}
</button>
</div>
);
}
export default LifeCycleDemo;
このように、マウント・更新・アンマウントの流れを意識してコードを書くことで、アプリの動作をより正確に理解できます。
Reactの基本をしっかり押さえることで、将来的に複雑なアプリを作るときにも役立ちます。
まとめ
Reactのライフサイクルにおける「マウント」「更新」「アンマウント」という3つの主要なフェーズについて詳しく解説してきましたが、いかがでしたでしょうか。これらの概念を理解することは、単にReactの文法を覚える以上の価値があります。なぜなら、Webアプリケーションがどのようにデータを処理し、画面を効率的に書き換えているのかという、フロントエンド開発の根幹部分を学ぶことになるからです。
これまでの内容を振り返ると、まず「マウント」はコンポーネントの誕生を意味します。ブラウザが初めて要素をレンダリングするこの瞬間、私たちはAPIからのデータ取得やタイマーの開始といった初期化処理を仕込みます。次に訪れるのが「更新(アップデート)」です。ユーザーがボタンをクリックしたり、入力フォームに文字を打ち込んだりすることで状態(state)が変化し、Reactは賢く画面の一部だけを書き換えます。そして最後が「アンマウント」。画面遷移などによってコンポーネントが役割を終えるとき、メモリ漏れを防ぐための「後片付け」を行う重要なステップです。
モダンなReact開発では、かつてのクラスコンポーネント時代のような複雑なメソッド(componentDidMountなど)を使い分ける必要はありません。現在はuseEffectという強力なフック一つで、これら全てのフェーズを直感的に制御できるようになっています。第二引数の依存配列(Dependency Array)を空にするのか、特定の変数を指定するのか、あるいはクリーンアップ関数を返すのか。この使い分けができるようになれば、Reactエンジニアとしてのレベルは格段に向上します。
実戦で役立つライフサイクルの応用コード
まとめとして、より実戦に近いコード例を見てみましょう。例えば、リアルタイムで現在時刻を表示しつつ、コンポーネントが消える際にタイマーをしっかり止める実装です。これはマウント・更新・アンマウントの全てが詰まった非常に良い練習材料になります。
import React, { useState, useEffect } from "react";
function RealTimeClock() {
const [time, setTime] = useState(new Date().toLocaleTimeString());
const [isActive, setIsActive] = useState(true);
useEffect(() => {
// 1. マウント時にタイマーを開始
console.log("時計が動き始めました(マウント)");
const timerId = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
// 3. アンマウント時にタイマーを停止(クリーンアップ)
return () => {
clearInterval(timerId);
console.log("時計が停止しました(アンマウント)");
};
}, []); // 空の配列なのでマウントとアンマウント時のみ動作
useEffect(() => {
// 2. 更新時にログを出力
console.log("時刻が更新されました:", time);
}, [time]); // timeが変化するたびに実行される
return (
<div className="p-4 border rounded shadow-sm">
<h3>現在の時刻</h3>
<p className="display-4">{time}</p>
<button
className="btn btn-danger"
onClick={() => setIsActive(false)}
>
時計を破棄する
</button>
</div>
);
}
export default function App() {
const [showClock, setShowClock] = useState(true);
return (
<div className="container mt-5">
{showClock ? (
<div>
<RealTimeClock />
<button className="btn btn-secondary mt-3" onClick={() => setShowClock(false)}>
コンポーネントを完全に削除
</button>
</div>
) : (
<button className="btn btn-primary" onClick={() => setShowClock(true)}>
時計を再表示する
</button>
)}
</div>
);
}
プログラミングの学習において、最も大切なのは「なぜその処理が必要なのか」を考えることです。Reactのライフサイクルを意識できるようになると、パフォーマンスの良い、バグの少ないアプリケーションが作れるようになります。まずは基本のマウント・更新・アンマウントを意識して、自分の手でコードを動かしてみることから始めてみましょう。
生徒
「先生、まとめまで読んでライフサイクルの全体像がかなりスッキリしてきました!要するに、useEffectの書き方一つで、生まれてから消えるまでの動きを全部コントロールできるってことですよね?」
先生
「その通りです!よく理解できましたね。特に重要なのは『後片付け』のアンマウント処理です。これを忘れると、画面には見えないけれど裏でタイマーがずっと動き続けて、アプリが重くなる原因になってしまうんですよ。」
生徒
「『部屋を出る時は電気を消す』という例えがすごく刺さりました。あと、更新(アップデート)の時に、どの変数が変わったかを監視する『依存配列』の仕組みも面白いですね。これを使えば、無駄な再描画を防いでサクサク動くアプリが作れそうです。」
先生
「素晴らしい視点です!大規模なアプリになればなるほど、その『無駄を省く』という考え方が効いてきます。ライフサイクルはReactの心臓部のようなものです。ここをマスターすれば、次はカスタムフックや、より高度な状態管理にもスムーズに進めますよ。」
生徒
「よし、もっと色々なコンポーネントを作って、コンソールログでマウントやアンマウントのタイミングを確認しながら練習してみます。ありがとうございました!」
先生
「その調子で頑張ってくださいね!もし分からなくなったら、いつでもこの『誕生・成長・引退』のサイクルを思い出してください。応援していますよ!」