クリーンアップのための 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 threeAxios と 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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- useEffect の基本:依存関係とクリーンアップ
- マウント時のデータ取得
- ローディング状態とエラー状態の処理
- クリーンアップのための AbortController