Next.js App Routerでエラーハンドリングを最適化する方法
この記事の目次
Next.js の App Router を使用している際、エラーハンドリングの方法に悩んでいる開発者向けの記事です。本記事では、**「カスタムエラーをシリアライズしてクライアントコンポーネントに受け渡し、再スローする」**という実装例を紹介します。この方法により、エラー内容を効率的にユーザーに伝えつつ、スムーズなデバッグを実現できます。
対象読者
- Next.js の App Router を使用している方
- サーバーサイドとクライアントサイド間でのエラー管理に課題を感じている方
環境情報
以下の環境で動作確認を行っています:
"next": "14.2.4", "react": "18", "typescript": "5",
結論
今回のエラーハンドリングの方法では、以下のフローを採用しました:
- サーバーコンポーネントでエラーを発生させる。
- エラーをカスタムクラスにシリアライズ。
- クライアントコンポーネントで再スローし、適切なUIでエラーを表示。
この方法により、エラー情報を正確に保持しつつ、柔軟なエラーハンドリングが可能になります。
実装手順
1. エラーハンドリング用 error.tsx
の作成
Next.js の 公式ドキュメント に基づき、error.tsx
を作成します。これにより、サーバーサイドおよびクライアントサイドの想定外エラーをキャッチ可能です。
以下のコードを src/app/error.tsx
に追加します:
2. サーバーコンポーネントでのエラー発生
サンプルとして、TodoリストをAPIから取得する機能を作成し、その中で意図的にエラーを発生させます。
page.tsx
の実装
import { fetchApi } from '@/app/_utils/fetchApi'; import { TodoList } from '@/components/TodoList'; export default async function Todos() { const todos = await fetchApi('https://jsonplaceholder.typicode.com/todos'); return ( <div> <h1>Todoリスト</h1> <TodoList todos={todos} /> </div> ); }
API通信でエラーを発生
fetchApi.ts
に意図的にエラーをスローするコードを記述します:
export async function fetchApi(url: string) { throw new Error('テストエラーが発生しました'); }
これにより、エラーが error.tsx
にキャッチされ、以下のようなエラーメッセージが表示されます:
3. カスタムエラーの導入
APIエラーをわかりやすく伝えるため、以下のようなカスタムエラークラスを作成します。
customError.ts
の作成
これにより、APIエラーの詳細情報をシリアライズ・デシリアライズできます。
4. クライアントコンポーネントでの再スロー
サーバーコンポーネントから渡されたエラーを再スローするためのコンポーネントを作成します。
DeserializeError.tsx
'use client'; import { APIError } from '@/app/_utils/customError'; export default function DeserializeError({ apiErrorObject }: { apiErrorObject: any }) { throw APIError.deserialize(apiErrorObject); // 再スロー }
5. サーバーコンポーネントの修正
APIError
をスローする場合、シリアライズ化して DeserializeError
に渡します。
修正後の page.tsx
import { APIError } from '@/app/_utils/customError'; import { fetchApi } from '@/app/_utils/fetchApi'; import DeserializeError from '@/components/DeserializeError'; export default async function Todos() { try { const todos = await fetchApi('https://jsonplaceholder.typicode.com/todos'); return ( <div> <h1>Todoリスト</h1> <TodoList todos={todos} /> </div> ); } catch (error) { if (error instanceof APIError) { return <DeserializeError apiErrorObject={error.serialize()} />; } throw error; } }
6. エラーUIの改善
カスタムエラー情報を利用して、ユーザー向けの分かりやすいエラー表示を実現します。
error.tsx
の修正
まとめ
この手法により、以下を実現できます:
- サーバーサイドとクライアントサイド間でのエラー情報の適切な受け渡し
- ユーザーに対するわかりやすいエラー表示
- デバッグの効率化
Next.js の App Router を活用し、柔軟かつ直感的なエラーハンドリングを実現しましょう!