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

ReactでFetch APIのレスポンスをキャッシュする方法を解説!初心者向けにやさしく丁寧に紹介

Fetch APIのレスポンスをキャッシュする方法
Fetch APIのレスポンスをキャッシュする方法

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

生徒

「ReactでAPIからデータを取得しているんですが、同じデータを何度も取りに行っていて、ちょっと無駄かなと思ってます…」

先生

「それなら“キャッシュ”を使ってみるといいですよ。取得したデータを一時的に保存して、次回からは保存したものを使うようにできます。」

生徒

「キャッシュって聞いたことあるけど、Reactでも簡単にできるんですか?」

先生

「はい、ReactとFetch APIを使って簡単にレスポンスをキャッシュできますよ。詳しく説明していきましょう!」

1. キャッシュとは何か?

1. キャッシュとは何か?
1. キャッシュとは何か?

キャッシュとは、一度取得したデータを一時的に保存しておく仕組みのことです。たとえば、同じAPIを何度も呼び出すと、サーバーにも負荷がかかりますし、通信時間もかかってしまいます。

そこで、一度取得したデータをブラウザのメモリやストレージに保存しておくことで、次回はその保存済みデータを使って表示を速くすることができます。

2. ReactでFetch APIを使うとは?

2. ReactでFetch APIを使うとは?
2. ReactでFetch APIを使うとは?

Reactでは、JavaScriptのFetch APIを使ってサーバーからデータを取得するのが一般的です。たとえば、天気情報や商品リストなどを外部APIから読み込むことがあります。

このFetch APIにキャッシュの仕組みを追加することで、通信の回数を減らして表示を速くすることができます。

3. メモリ内キャッシュの基本的な仕組み

3. メモリ内キャッシュの基本的な仕組み
3. メモリ内キャッシュの基本的な仕組み

まずはReactのコンポーネント内に「キャッシュ用の変数」を用意して、APIレスポンスを一時保存する方法を見てみましょう。


import React, { useState } from "react";

const cache = {};

function App() {
  const [data, setData] = useState("データ未取得");

  const fetchData = async () => {
    const url = "https://api.example.com/info";

    if (cache[url]) {
      setData(cache[url]);
      return;
    }

    const response = await fetch(url);
    const result = await response.json();
    cache[url] = result.message;
    setData(result.message);
  };

  return (
    <div>
      <h1>{data}</h1>
      <button onClick={fetchData}>データ取得</button>
    </div>
  );
}

export default App;
(画面に「データ未取得」と表示され、ボタンを押すとAPIからデータを取得し、その後はキャッシュされた内容が表示されます)

4. キャッシュの保存先はどこ?

4. キャッシュの保存先はどこ?
4. キャッシュの保存先はどこ?

上記の例では、const cache = {}という形でJavaScriptのオブジェクトに保存しています。これは「メモリ内キャッシュ」と呼ばれます。

ただしこの方法は、ページを再読み込みするとデータが消えてしまいます。より永続的に保存したい場合は「localStorage」や「sessionStorage」を使います。

5. localStorageを使ったキャッシュ方法

5. localStorageを使ったキャッシュ方法
5. localStorageを使ったキャッシュ方法

localStorageを使えば、ページを再読み込みしてもキャッシュされたデータを保持できます。例としては次のようになります。


const fetchData = async () => {
  const cacheKey = "api_cache";
  const cached = localStorage.getItem(cacheKey);

  if (cached) {
    setData(cached);
    return;
  }

  const response = await fetch("https://api.example.com/info");
  const result = await response.json();

  localStorage.setItem(cacheKey, result.message);
  setData(result.message);
};

このように書くことで、一度取得したデータをブラウザに保存して、次回以降は保存済みデータを表示できます。

6. キャッシュに有効期限をつけるには?

6. キャッシュに有効期限をつけるには?
6. キャッシュに有効期限をつけるには?

キャッシュは便利ですが、ずっと古いままでは意味がありません。そこで、保存時に「タイムスタンプ(保存時間)」を一緒に保存して、一定時間が過ぎたら再取得するという工夫もできます。


const fetchData = async () => {
  const cacheKey = "api_cache_v2";
  const cacheTimeKey = "api_cache_time";
  const cached = localStorage.getItem(cacheKey);
  const cacheTime = localStorage.getItem(cacheTimeKey);

  const now = Date.now();
  const oneHour = 1000 * 60 * 60;

  if (cached && cacheTime && now - cacheTime < oneHour) {
    setData(cached);
    return;
  }

  const response = await fetch("https://api.example.com/info");
  const result = await response.json();

  localStorage.setItem(cacheKey, result.message);
  localStorage.setItem(cacheTimeKey, now);
  setData(result.message);
};

これで「1時間以内はキャッシュを使う、それ以降は再取得する」といった処理が可能になります。

7. キャッシュ処理が便利な場面とは?

7. キャッシュ処理が便利な場面とは?
7. キャッシュ処理が便利な場面とは?
  • 変更の少ないデータを扱うとき(例:都道府県一覧、カテゴリリスト)
  • 通信量を減らしたいとき(モバイル環境など)
  • 表示を速くしたいとき(UX向上のため)

Reactでキャッシュを使うことで、サーバーとの通信回数を減らし、アプリのレスポンスを改善することができます。

まとめ

まとめ
まとめ

ここまでReactにおけるFetch APIのレスポンスキャッシュについて、基本的なメモリ内キャッシュからlocalStorageを活用した永続化、さらには有効期限の設定方法まで詳しく解説してきました。フロントエンド開発において、APIからのデータ取得は避けては通れない道ですが、ただ取得するだけでなく「いかに効率よく管理するか」が、ユーザー体験(UX)を劇的に向上させる鍵となります。

特にReactのようなシングルページアプリケーション(SPA)では、画面遷移のたびに同じデータをフェッチしてしまうと、ネットワーク帯域の無駄遣いになるだけでなく、ユーザーに「待機時間」というストレスを与えてしまいます。今回ご紹介した手法を取り入れることで、瞬時に画面が表示される心地よいアプリを目指すことができます。

実践的なキャッシュ戦略の振り返り

キャッシュ戦略を選ぶ際は、扱うデータの性質を見極めることが重要です。短期間のセッションで十分な場合はコンポーネント外の変数やステートを利用し、ユーザーがブラウザを閉じても保持したい場合はストレージを利用しましょう。また、最新性が求められるニュースや株価のようなデータには、キャッシュの有効期限(TTL)を短く設定するか、SWR(Stale-While-Revalidate)のような高度なライブラリの検討も視野に入れると良いでしょう。

応用:カスタムフックによるキャッシュの共通化

実際のプロジェクトでは、複数のコンポーネントで同じようなキャッシュ処理を書くのは非効率です。そこで、再利用可能な「カスタムフック」としてロジックを切り出すのがReactらしい書き方です。以下に、汎用的なキャッシュ機能付きデータフェッチフックの例を紹介します。


import { useState, useEffect } from "react";

/**
 * キャッシュ機能付きカスタムフック
 * @param {string} url 取得先のURL
 * @returns {object} { data, loading, error }
 */
const useCachedFetch = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        // localStorageからキャッシュを確認
        const cachedData = localStorage.getItem(url);
        if (cachedData) {
          setData(JSON.parse(cachedData));
          setLoading(false);
          return;
        }

        // キャッシュがない場合はフェッチを実行
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error("データの取得に失敗しました");
        }
        const result = await response.json();

        // 取得データをキャッシュに保存
        localStorage.setItem(url, JSON.stringify(result));
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
};

export default useCachedFetch;
(このフックを呼び出すだけで、初回はAPI通信を行い、2回目以降はlocalStorageから即座にデータを取得して表示します。loading状態の管理も自動で行われます)

このようにロジックをカプセル化することで、コンポーネント側のコードは非常にスッキリします。メンテナンス性も高まり、バグの混入を防ぐことにも繋がります。Reactの基本をマスターした後は、こうした「自分だけの便利な道具」を作っていくのが上達への近道です。

これからのステップ

もし、より大規模なアプリケーションを開発する場合は、自前でキャッシュロジックを書く代わりに「TanStack Query (React Query)」や「SWR」といったライブラリを導入することも検討してみてください。これらのライブラリは、今回学んだ「キャッシュの保存」「有効期限の管理」「データの再取得」といった機能をさらに高度に、かつ簡単に実装できるように設計されています。

しかし、ライブラリが裏側で何をやっているのかを理解するためには、今回のような生のJavaScript/Reactによる実装経験が不可欠です。まずは小さなプロジェクトから、自分の手でキャッシュを制御する楽しさを味わってみてください。パフォーマンスが最適化されたアプリは、開発者にとってもユーザーにとっても最高の成果物になります。

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

生徒

「先生、ありがとうございました!キャッシュを使うことで、あんなに何度も走っていたAPIリクエストが劇的に減って、アプリの動きがサクサクになりました。特にカスタムフックにする方法は、他のページでも使い回せるので感動しました!」

先生

「それは良かったです!動作が速くなると、作っている自分自身も楽しくなりますよね。実は、ユーザーが気づかないような数ミリ秒の短縮が、アプリの継続率や満足度に大きく影響するんですよ。エンジニアとしての細かなこだわりが、良いサービスを作ります。」

生徒

「なるほど…。でも一つ気になったのですが、もしサーバー側のデータが更新された場合、キャッシュが残っていると古い情報が表示され続けてしまいますよね?そのあたりはどう制御するのが正解なんでしょうか。」

先生

「鋭い指摘ですね!それが『キャッシュの無効化(Invalidation)』という、実はコンピュータサイエンスで最も難しいと言われる課題の一つです。解決策としては、今回紹介した有効期限(TTL)を設ける方法のほかに、データ更新用のボタンを用意して手動でキャッシュをクリアしたり、特定の操作(データの保存や削除)が行われたタイミングでキャッシュを破棄するロジックを組んだりします。」

生徒

「キャッシュの無効化…奥が深いですね。次は、特定の条件でキャッシュを更新する仕組みにも挑戦してみたいです!」

先生

「その意気です!まずは今回学んだlocalStorageの使い方をマスターして、データの型やエラーハンドリングも意識してみてください。TypeScriptを使っているなら、APIレスポンスの型定義をしっかり行うことで、キャッシュから取り出したデータも安全に扱えるようになりますよ。」

生徒

「はい、次はTSXで型安全なキャッシュ機能を作ってみます!コードを書くのがもっと楽しくなってきました。」

先生

「素晴らしいですね。もし詰まったらいつでも聞いてください。Reactの世界は広いですが、一歩ずつ進んでいけば必ず使いこなせるようになりますよ。頑張りましょう!」

カテゴリの一覧へ
新着記事
New1
React
Reactコンポーネントの再利用と分割を完全マスター!初心者でもわかるコンポーネント設計
New2
React
ReactでAxiosインターセプターの使い方を完全ガイド!初心者でもわかるリクエストとレスポンスの処理方法
New3
React
JSXの書き方!初心者でもわかるReactタグと属性の基本ルール解説
New4
React
ReactとDockerを使った開発環境構築の基本を徹底解説!初心者でもわかるReactとDockerの連携方法
人気記事
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
create-react-appでReactプロジェクトを作成する手順を初心者向けに完全解説!
No.7
Java&Spring記事人気No7
React
ReactのuseStateとuseEffectでよくあるエラーと解決方法ガイド!初心者でもわかるReactフック
No.8
Java&Spring記事人気No8
React
Reactのフォーム処理でよくあるエラーと解決法を完全解説!初心者でも安心して学べるReact入門