エラーハンドリング戦略
API連携では「うまくいかないとき」にどう振る舞うかが品質を左右します。ユーザー体験を損なわず、開発中も原因を素早く特定できる戦略をまとめます(安心感が違います)。
この記事で学べること
- エラーの分類(ユーザー起因/ネットワーク/サーバー)
- 表示・ログ・再試行の基本設計
- フロントエンドの実装パターン(fetch/SWR)
エラーの分類
- 入力エラー(400系): フォームのバリデーション結果など
- 認証/認可エラー(401/403): ログインや権限が必要
- リソース未検出(404): URLやID間違い
- レート制限(429): 呼びすぎ注意。待って再試行
- サーバーエラー(5xx): サーバー側の問題。時間を置いて再試行
- ネットワークエラー: オフライン/タイムアウト/プロキシ問題など
UIでの基本方針
- 明確なメッセージ: 「何が起きたか」「次に何をすべきか」
- 再試行ボタン: ユーザー主体で回復できる道を残す
- 重要データはスケルトン/プレースホルダ表示で認知負荷を軽減
- クリティカル時のみダイアログ。通常は画面内に控えめに表示
fetch の標準実装
export async function requestJSON<T>(
input: RequestInfo,
init?: RequestInit,
): Promise<T> {
try {
const res = await fetch(input, init);
if (!res.ok) {
let message = `HTTP ${res.status}`;
try {
const body = await res.json();
message = body.message || message;
} catch {}
throw new Error(message);
}
const ct = res.headers.get("content-type") || "";
if (ct.includes("application/json")) return res.json();
throw new Error("Unexpected content type");
} catch (e) {
if ((e as any)?.name === "AbortError") throw e; // キャンセルはそのまま
// ネットワーク系
if (e instanceof TypeError) {
throw new Error(
"ネットワークに接続できません(オフライン/プロキシ/SSL など)",
);
}
throw e;
}
}
SWRでの戦略
import useSWR, { SWRConfig } from "swr";
const fetchJSON = <T,>(url: string) =>
fetch(url).then(async (r) => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json() as Promise<T>;
});
function User() {
const { data, error, isLoading, mutate } = useSWR("/api/me", fetchJSON);
if (isLoading) return <p>読み込み中</p>;
if (error) return <button onClick={() => mutate()}>再試行</button>;
return <div>{data.name}</div>;
}
export function Providers({ children }: { children: React.ReactNode }) {
return (
<SWRConfig
value={{
onError: (err) => {
// グローバル通知やSentry送信など
console.error("[SWR Error]", err);
},
shouldRetryOnError: true,
errorRetryCount: 3,
}}
>
{children}
</SWRConfig>
);
}
ログと監視
- ユーザー向け表示と開発者向けログを分離(混ぜない)
- 予期せぬ例外はSentryなどに送信(個人情報に注意)
- 再現手順/レスポンス/トレースIDを記録して解析可能に
やってみよう!
- 404/500/ネットワーク遮断を擬似的に作り、UIメッセージと再試行動作を確認
- SWRの
errorRetryCountを増やしてバックオフ動作を観察
ポイント(まとめ)
- エラーは種類ごとに対処を分ける(メッセージ/再試行/遅延)
- fetchは
res.okとContent-Typeを確認して丁寧に処理 - SWRでは
onErrorやmutateで回復体験を設計 - ログは「利用者の安心」と「開発者の調査」を両立
参考リンク
- MDN: fetch https://developer.mozilla.org/ja/docs/Web/API/Fetch_API
- SWR 公式 https://swr.vercel.app/ja