カテゴリ: React 更新日: 2026/02/04

ReactのcomponentWillUnmountとクリーンアップ関数を徹底解説!初心者でもわかるライフサイクルの基本

componentWillUnmountとクリーンアップ関数の使い方
componentWillUnmountとクリーンアップ関数の使い方

先生と生徒の会話形式で理解しよう

生徒

「先生、ReactのcomponentWillUnmountって何をするものなんですか?」

先生

「良い質問ですね。componentWillUnmountは、コンポーネントが画面から消えるときに実行される関数なんです。」

生徒

「画面から消えるときって、どういうときですか?」

先生

「例えば、別のページに移動したり、条件分岐でコンポーネントを非表示にしたときなどですね。そのときに後片付けをするのがcomponentWillUnmountの役目です。」

生徒

「なるほど。じゃあ、関数コンポーネントではどうやって後片付けをするんですか?」

先生

「関数コンポーネントでは、useEffectというフックの中で“クリーンアップ関数”を使います。これがcomponentWillUnmountと同じ役割を果たしますよ。」

1. componentWillUnmountとは?

1. componentWillUnmountとは?
1. componentWillUnmountとは?

Reactのクラスコンポーネントでは、ライフサイクルメソッドと呼ばれる関数を使って、コンポーネントの動作タイミングを制御できます。その中のひとつがcomponentWillUnmountです。

componentWillUnmountは、コンポーネントが画面から削除される直前に実行されるメソッドで、主に「後片付け」を行うために使われます。

たとえば、以下のような場合に利用します:

  • タイマー(setIntervalやsetTimeout)の停止
  • イベントリスナー(addEventListener)の削除
  • API通信のキャンセル
  • WebSocketや外部リソースのクローズ処理

import React from "react";

class Timer extends React.Component {
  componentDidMount() {
    this.timer = setInterval(() => {
      console.log("タイマーが動作中");
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
    console.log("タイマーを停止しました");
  }

  render() {
    return <h1>タイマー動作中...</h1>;
  }
}

export default Timer;
(コンポーネントが表示されている間は1秒ごとにログが出力され、画面から消えると「タイマーを停止しました」と表示されます)

2. 関数コンポーネントでのクリーンアップ関数

2. 関数コンポーネントでのクリーンアップ関数
2. 関数コンポーネントでのクリーンアップ関数

React Hooks(フック)を使った関数コンポーネントでは、クラスのようにcomponentWillUnmountを使うことはできません。その代わりに、useEffectフックの中で「クリーンアップ関数」を定義します。

クリーンアップ関数とは、useEffectの中でreturn文を使って定義する関数のことです。この関数は、コンポーネントが削除されるとき、または依存する値が変わる前に自動的に呼び出されます。


import React, { useEffect } from "react";

function Timer() {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log("タイマーが動作中");
    }, 1000);

    // クリーンアップ関数
    return () => {
      clearInterval(timer);
      console.log("タイマーを停止しました");
    };
  }, []);

  return <h1>タイマー動作中...</h1>;
}

export default Timer;
(同じく1秒ごとにログが出力され、コンポーネントが画面から消えるとタイマーが止まります)

つまり、クリーンアップ関数は「後片付け専門の関数」であり、componentWillUnmountと同じ役割を果たします。関数コンポーネントではこの方法でリソースをきれいに解放します。

3. クリーンアップ関数が呼ばれるタイミング

3. クリーンアップ関数が呼ばれるタイミング
3. クリーンアップ関数が呼ばれるタイミング

クリーンアップ関数は、次の2つのタイミングで呼び出されます。

  • コンポーネントがアンマウント(削除)されるとき
  • useEffectの依存配列(第2引数)の値が変化する直前

依存配列とは、useEffect(() => {}, [値])の中の[値]部分です。この配列に指定された変数が変わると、古いエフェクトがクリーンアップされ、新しいエフェクトが実行されます。


import React, { useState, useEffect } from "react";

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("カウントが変更されました:", count);

    return () => {
      console.log("前のカウントをクリーンアップ:", count);
    };
  }, [count]);

  return (
    <div>
      <p>現在のカウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>カウントを増やす</button>
    </div>
  );
}

export default Example;
(ボタンをクリックするたびに、「前のカウントをクリーンアップ」が表示され、古い値の後片付けが行われます)

このようにクリーンアップ関数を使うことで、Reactは効率的にメモリを管理し、不要な動作を防ぐことができます。

4. componentWillUnmountとクリーンアップ関数の違い

4. componentWillUnmountとクリーンアップ関数の違い
4. componentWillUnmountとクリーンアップ関数の違い
項目 componentWillUnmount(クラス) クリーンアップ関数(関数コンポーネント)
使う場所 クラスコンポーネント内 useEffectの中
呼ばれるタイミング コンポーネントが削除される直前 削除時・依存値が更新される直前
記述方法 メソッドとして定義 return文で定義

どちらも「後片付け」をするという点では同じですが、記述の仕方と使う場所が異なります。React Hooksを使う現在では、クリーンアップ関数を使う書き方が主流です。

5. クリーンアップ関数の実践的な使い方

5. クリーンアップ関数の実践的な使い方
5. クリーンアップ関数の実践的な使い方

最後に、実際の開発でよくある使い方を紹介します。たとえば、ブラウザのイベントを監視している場合、コンポーネントが削除されるときにリスナーを解除しないと、不要な処理が残ってしまいます。


import React, { useEffect } from "react";

function WindowResizeLogger() {
  useEffect(() => {
    const handleResize = () => {
      console.log("ウィンドウサイズ:", window.innerWidth);
    };

    window.addEventListener("resize", handleResize);

    return () => {
      window.removeEventListener("resize", handleResize);
      console.log("リスナーを解除しました");
    };
  }, []);

  return <h1>ウィンドウサイズを監視中...</h1>;
}

export default WindowResizeLogger;
(ウィンドウのサイズを変えるとログが出力され、コンポーネントが消えるとリスナーが解除されます)

このようにクリーンアップ関数は、アプリの安定性やパフォーマンスを保つうえで非常に重要な役割を果たします。

まとめ

まとめ
まとめ

Reactの開発において、コンポーネントの「後片付け」を正しく理解することは、アプリケーションの品質を左右する非常に重要なステップです。今回は、クラスコンポーネント時代のcomponentWillUnmountから、現代の主流である関数コンポーネントでのuseEffectを用いたクリーンアップ関数まで、その役割と使い方を詳しく解説してきました。

特に初心者の方が躓きやすいポイントは、「なぜ後片付けが必要なのか」という点です。JavaScriptのタイマー処理やイベントリスナー、外部APIとの通信などは、コンポーネントが画面から消えた後もブラウザのメモリ上に残り続けてしまうことがあります。これを放置すると、メモリリークの原因となり、アプリが次第に重くなったり、予期せぬエラーを引き起こしたりします。プログラミングにおいて、開いたドアを閉める、使った道具を片付けるといった「終わりの儀式」をコードで表現するのが、クリーンアップの役割なのです。

学んだポイントの振り返り

  • componentWillUnmountの役割:コンポーネントが破棄される直前に一度だけ実行される「お別れの挨拶」のようなメソッド。
  • useEffectでの代替:関数コンポーネントでは、useEffectの戻り値(return)に「クリーンアップ関数」を指定することで、同様の処理を実現。
  • 実行のタイミング:アンマウント時だけでなく、依存配列(Dependency Array)の値が更新される直前にも、古い状態をリセットするために実行される。
  • 実践的な活用例:setIntervalの解除、addEventListenerの削除、そして不要になったAPIリクエストの中断などが代表的。

具体的な実装例:複数条件でのクリーンアップ

より実践的なコードを見てみましょう。例えば、ユーザーIDが変更されるたびにデータを取得し、その間にコンポーネントが切り替わったりIDが変わったりした場合のクリーンアップは以下のように記述します。


import React, { useState, useEffect } from "react";

function UserProfile({ userId }) {
  const [userData, setUserData] = useState(null);

  useEffect(() => {
    let isMounted = true; // コンポーネントがマウントされているかどうかのフラグ

    console.log(`ユーザー ${userId} のデータを取得開始...`);
    
    // 擬似的なAPIコール
    fetch(`https://api.example.com/user/${userId}`)
      .then(response => response.json())
      .then(data => {
        if (isMounted) {
          setUserData(data);
          console.log("データをセットしました");
        }
      });

    // クリーンアップ関数
    return () => {
      isMounted = false; // アンマウント時にフラグを倒す
      console.log(`ユーザー ${userId} の処理を中断または破棄しました`);
    };
  }, [userId]); // userIdが変わるたびに実行

  return (
    <div>
      {userData ? (
        <h1>ユーザー名: {userData.name}</h1>
      ) : (
        <p>読み込み中...</p>
      )}
    </div>
  );
}

export default UserProfile;
(userIdが切り替わると、前のリクエストの結果が反映されないようフラグが更新され、安全にデータの同期が行われます)

このように、useEffectを活用することで、クラスコンポーネントよりも柔軟かつ簡潔に「副作用(Side Effects)」を管理できるようになります。これからのモダンなReact開発では、フック(Hooks)を使いこなし、リソースを適切に解放する癖をつけておきましょう。

先生と生徒の振り返り会話

生徒

「先生、まとめを読んでクリーンアップ関数の重要性がさらに深く理解できました!要するに、使いっぱなしにしないで『お片付け』をするのがマナーだってことですね。」

先生

「その通りです!リアルの世界と同じで、出しっぱなしにすると部屋(メモリ)が散らかってしまいますからね。プログラミングにおけるマナーは、アプリのパフォーマンスに直結するんですよ。」

生徒

「コードの中でreturn () => { ... }と書くだけで、古い処理をリセットできるのは便利ですね。でも、依存配列の[userId]がある場合とない場合では、動きが全然違うんですよね?」

先生

「よく気づきましたね。空の配列[]ならアンマウント時だけですが、値が入っていると、その値が変わるたびに『古い方のクリーンアップ』と『新しい方のエフェクト』が交互に走ります。これがReactの賢いところです。」

生徒

「なるほど。だから前のカウントや前の通信をキャンセルできるんですね。最初は少し複雑に感じましたが、実際に動かしてみると納得がいきました。これからはaddEventListenerを使ったら必ずセットでremoveEventListenerを書くようにします!」

先生

「素晴らしい意気込みですね。その積み重ねが、バグの少ない、ユーザーに優しいアプリケーション作りへと繋がります。ライフサイクルをマスターすれば、中級者への道もすぐそこですよ!」

カテゴリの一覧へ
新着記事
New1
React
ReactのuseEffectでAPIを呼び出す正しい方法を解説!初心者でもできる非同期処理の基本
New2
React
ReactのuseEffectでイベントリスナーを登録・解除する方法を徹底解説!初心者向けReactフック入門
New3
React
Reactコンポーネントの再利用と分割を完全マスター!初心者でもわかるコンポーネント設計
New4
React
ReactでAxiosインターセプターの使い方を完全ガイド!初心者でもわかるリクエストとレスポンスの処理方法
人気記事
No.1
Java&Spring記事人気No1
React
ReactでonChangeイベントを使ってフォーム入力値を管理する方法を初心者向けに解説
No.2
Java&Spring記事人気No2
React
ReactとTypeScriptの環境構築をやさしく解説!Viteとtsconfigの設定も丁寧に紹介
No.3
Java&Spring記事人気No3
React
Reactのイベントハンドリングのアンチパターンまとめ!初心者でもわかる注意点
No.4
Java&Spring記事人気No4
React
Reactのカスタムフックの作り方を完全ガイド!再利用可能なロジックを切り出す仕組み
No.5
Java&Spring記事人気No5
React
ReactでFetch APIのローディング状態を管理する方法|初心者にもわかる解説
No.6
Java&Spring記事人気No6
React
Reactでファイルアップロードを実装する方法を解説!Fetch APIで画像やPDFを送る仕組みを初心者向けに紹介
No.7
Java&Spring記事人気No7
React
ReactのuseStateとuseEffectでよくあるエラーと解決方法ガイド!初心者でもわかるReactフック
No.8
Java&Spring記事人気No8
React
ViteでReact開発環境を構築する手順を完全ガイド!初心者でもできるReactの環境構築