0Pricing
Frontend Academy · レッスン

クリーンアップのための AbortController

AbortController を作成して signal を fetch に渡し、アンマウントされたコンポーネントの state 更新を防ぐため、クリーンアップ関数で進行中のリクエストをキャンセルします。

「クリーンアップのための AbortController」はCoddyKit上の無料Frontend Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはFrontend Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Frontend Academyコースには全4レッスンが含まれています。

fetch リクエストをキャンセルする理由

コンポーネントがアンマウントされたり、再取得が行われたりしても、以前のリクエストが処理中のままになっていることがあります。そのリクエストが新しいリクエストの後に完了すると、古いデータで新しいデータが上書きされます。AbortController を使用すると、処理中のリクエストを適切にキャンセルできます。

AbortController の基本

AbortController を作成し、その signal を fetch に渡して、controller.abort() を呼び出すとキャンセルできます。キャンセルされると fetch は AbortError をスローします。

const controller = new AbortController();

try {
  const res = await fetch('/api/data', { signal: controller.signal });
  const data = await res.json();
  setData(data);
} catch (err) {
  if (err instanceof DOMException && err.name === 'AbortError') {
    console.log('Request was cancelled');
  } else {
    setError((err as Error).message);
  }
}

// To cancel:
controller.abort();

useEffect のクリーンアップでの使用

エフェクトの開始時に AbortController を作成し、クリーンアップ関数で abort() を呼び出します。これにより、依存関係が変化したときやコンポーネントがアンマウントされたときに、リクエストが自動的にキャンセルされます。

useEffect(() => {
  const controller = new AbortController();

  async function load() {
    try {
      const res = await fetch(`/api/user/${userId}`, { signal: controller.signal });
      if (!res.ok) throw new Error(`${res.status}`);
      setUser(await res.json());
    } catch (err) {
      if ((err as DOMException).name !== 'AbortError') {
        setError((err as Error).message);
      }
    }
  }

  load();
  return () => controller.abort();
}, [userId]);

AbortError とネットワークエラーの比較

キャンセルされたリクエストは、name が「AbortError」の DOMException をスローします。必ずこれを個別に確認し、ユーザーに表示するエラーとして扱わないでください。これは想定されたクリーンアップ処理です。

signal.aborted プロパティ

シグナルがキャンセルされたかどうかを確認するには、controller.signal.aborted を確認します。非同期コードで setState を呼び出す前の確認に便利です。

const data = await fetchData();
if (!controller.signal.aborted) {
  setData(data); // safe to update state
}

複数のリクエストのキャンセル

同じ signal をすべてのリクエストに渡すことで、1 つの AbortController から複数の fetch リクエストをキャンセルできます。

const controller = new AbortController();
const { signal } = controller;

await Promise.all([
  fetch('/api/users',    { signal }),
  fetch('/api/products', { signal }),
  fetch('/api/settings', { signal }),
]);

controller.abort(); // cancels all three

Axios と AbortController

Axios では、設定の signal オプションを通じて AbortController の signal を使用できます。signal のインターフェースは fetch と同じです。

const controller = new AbortController();
await axios.get('/api/data', { signal: controller.signal });

// In cleanup:
return () => controller.abort();

React Query による自動処理

TanStack Query(React Query)を使用すると、キャンセル処理が自動的に行われます。React Query が内部で controller を作成し、キャンセルします。手動の fetch パターンよりも React Query を推奨する理由の 1 つです。

AbortController によるタイムアウト

AbortController と setTimeout を組み合わせて、リクエストのタイムアウトを実装します。

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5s timeout

try {
  const data = await fetch(url, { signal: controller.signal });
  // ...
} finally {
  clearTimeout(timeoutId);
}

AbortSignal.timeout() — 最新の簡易方法

最新のブラウザーでは、AbortSignal.timeout(ms) を使うと、手動で controller を用意しなくても、指定した時間が経過した後に自動的にキャンセルされる signal を作成できます。

const res = await fetch('/api/data', {
  signal: AbortSignal.timeout(5000) // 5 second timeout
});

React 18 Strict Mode ではクリーンアップが重要

React 18 Strict Mode は開発中にエフェクトを 2 回マウントします。AbortController のクリーンアップがないと、fetch が 2 回実行されたり、アンマウント済みのコンポーネントの state を更新したりする警告が表示される可能性があります。クリーンアップパターンによって、これらの両方を防げます。

確認問題

コンポーネントの再レンダリング後に古いネットワークレスポンスが state を更新するのを防ぐには、どうすればよいですか?

まとめ:AbortController

エフェクトごとに AbortController を作成します。signal を fetch/axios に渡します。クリーンアップ関数で abort します。AbortError は想定されたエラーなので無視します。非同期コードで setState を呼び出す前に signal.aborted を確認します。1 つの controller で複数のリクエストをキャンセルできます。タイムアウトには AbortSignal.timeout() を使用します。React Query では、これらがすべて自動的に処理されます。

よくある質問

「クリーンアップのための AbortController」レッスンは無料ですか?

はい。「クリーンアップのための AbortController」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Frontend Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Frontend Academyコースには全4レッスンが含まれています。

「クリーンアップのための AbortController」で何を学びますか?

AbortController を作成して signal を fetch に渡し、アンマウントされたコンポーネントの state 更新を防ぐため、クリーンアップ関数で進行中のリクエストをキャンセルします。 ブラウザで直接実行するハンズオンコードでFrontend Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Frontend Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのFrontend Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「クリーンアップのための AbortController」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このFrontend Academyレッスンでコードを書いて実行できますか?

はい。すべてのFrontend Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. useEffect の基本:依存関係とクリーンアップ
  2. マウント時のデータ取得
  3. ローディング状態とエラー状態の処理
  4. クリーンアップのための AbortController
← Frontend Academyに戻る