はじめに
こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
フロントエンド開発では API リクエストを投げた後に 「もう結果が不要になった」 ということがよくあります。
- 検索フォームで入力するたびにリクエストする場合、古いリクエストは無駄になる
- React コンポーネントがアンマウントされたあとにリクエストが残っていると、メモリリークや警告の原因になる
こうした「不要になったリクエスト」を止められる仕組みが AbortController です。
この記事では、AbortController の基本から、実際の使いどころまでを整理します。
基本の使い方
import axios from 'axios';
async function fetchData() {
const controller = new AbortController();
try {
const res = await axios.get('/api/data', { signal: controller.signal });
console.log(res.data);
} catch (err) {
if (axios.isCancel(err)) {
console.log('リクエストがキャンセルされました');
} else {
console.error('通信エラー:', err);
}
}
// 必要なくなったら中断
controller.abort();
}
fetchData();
ポイント:
- axios のオプションに
signal
を渡す -
controller.abort()
を呼ぶとAxiosError
が投げられる -
axios.isCancel(err)
でキャンセルかどうかを判定できる
React での使いどころ
1. useEffect のクリーンアップ
コンポーネントが消えるときにリクエストをキャンセル。
import { useEffect, useState } from 'react';
import axios from 'axios';
export const UserList = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
const controller = new AbortController();
const fetchUsers = async () => {
try {
const res = await axios.get('/api/users', {
signal: controller.signal,
});
setUsers(res.data);
} catch (err) {
if (!axios.isCancel(err)) {
console.error('ユーザー取得に失敗:', err);
}
}
};
fetchUsers();
return () => {
controller.abort(); // クリーンアップ時にキャンセル
};
}, []);
return (
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
};
2. 入力中の古いリクエストを破棄する
検索フォームなどでは「新しいキーワード入力時に古いリクエストをキャンセル」すると UX が良くなる。
import { useEffect, useState } from 'react';
import axios from 'axios';
export const SearchBox = ({ keyword }: { keyword: string }) => {
const [result, setResult] = useState([]);
useEffect(() => {
const controller = new AbortController();
const fetchSearch = async () => {
try {
const res = await axios.get(`/api/search?q=${keyword}`, {
signal: controller.signal,
});
setResult(res.data);
} catch (err) {
if (!axios.isCancel(err)) {
console.error('検索失敗:', err);
}
}
};
fetchSearch();
return () => {
controller.abort(); // 新しい検索時に前のリクエストをキャンセル
};
}, [keyword]);
return <div>{JSON.stringify(result)}</div>;
};
まとめ
- AbortController は リクエストを途中で止める仕組み
- axios では
signal
を渡し、不要になったらabort()
- React では
useEffect
のクリーンアップや検索フォームに特に有効