第84章:エラー時の表示を整える(error.tsx活用)🧯✨
この章では、「通信に失敗した」「バグで落ちた」みたいな 予期しないエラー が起きた時に、ユーザーにやさしい画面を出す方法をやるよ〜!😊💡
Next.js(App Router)は error.tsx を置くだけ で、そのルート区間にエラーバウンダリー(保険)を作れます🛟✨ (Next.js)
1) error.tsx って何?🤔💭
エラーには大きく2種類あるよ👇
- ✅ 想定内のエラー:バリデーション失敗、入力ミス、ログイン失敗…など(戻り値で扱うのが基本) (Next.js)
- 💥 想定外のエラー:バグ、例外、通信まわりの想定外…など(投げたエラーを境界で受ける) (Next.js)
error.tsx はこの 想定外のエラー を受け止めて、クラッシュの代わりに“かわりの画面”を表示してくれるファイルだよ🧯✨ (Next.js)
しかもポイントはこれ👇
error.tsxは ルートセグメント(そのフォルダ配下) のエラーをまとめて受け止める🧱 (Next.js)- Client Componentである必要があるので、先頭に
'use client'が必須!🧡 (Next.js) - propsで
errorとreset()を受け取れるよ🔁 (Next.js)
2) 仕組みの図解(ざっくり)🧠🗺️
reset() は「もう一回その区間を描画しなおしてみる」って感じだよ🔁 (Next.js)
3) 実際に作ってみよう!🛠️🎀(わざと失敗→エラー画面)
3-1) フォルダ構成📁✨
app/demo-error/ を作って、その中に page.tsx と error.tsx を置くよ!
app/
demo-error/
page.tsx
error.tsx
3-2) page.tsx(失敗するfetchを用意)📥💥
?fail=1 が付いてたら 壊れたURL にfetchして、わざとエラーにするよ😈✨
// app/demo-error/page.tsx
type PageProps = {
searchParams: { fail?: string }
}
export default async function Page({ searchParams }: PageProps) {
const shouldFail = searchParams.fail === '1'
const url = shouldFail
? 'https://jsonplaceholder.typicode.com/__broken__' // わざと壊す💥
: 'https://jsonplaceholder.typicode.com/posts?_limit=5'
const res = await fetch(url)
// fetch自体が成功しても、404/500なら res.ok が false だよ⚠️
if (!res.ok) {
throw new Error(`データ取得に失敗しました(status: ${res.status})`)
}
const posts: Array<{ id: number; title: string }> = await res.json()
return (
<main style={{ padding: 16 }}>
<h1>デモ:エラー表示を整える🧯✨</h1>
<p>
ふつうの表示🙂:
<a href="/demo-error" style={{ marginLeft: 8 }}>
/demo-error
</a>
</p>
<p>
わざと失敗😵:
<a href="/demo-error?fail=1" style={{ marginLeft: 8 }}>
/demo-error?fail=1
</a>
</p>
<hr style={{ margin: '16px 0' }} />
<ul>
{posts.map((p) => (
<li key={p.id}>{p.title}</li>
))}
</ul>
</main>
)
}
3-3) error.tsx(エラー画面を作る)🧯💖
error.tsx は 必ずClient Component なので先頭に 'use client' を書くよ! (Next.js)
reset() をボタンに繋ぐと「もう一回!」ができる✨ (Next.js)
// app/demo-error/error.tsx
'use client'
import { useEffect } from 'react'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
useEffect(() => {
// 本番では監視ツールに送ったりする想定📡
console.error(error)
}, [error])
return (
<main style={{ padding: 16 }}>
<h1>ごめんね、エラーが起きちゃった…😵💫🧯</h1>
<p style={{ marginTop: 8 }}>
もう一回やってみる?🔁
</p>
<div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
<button onClick={() => reset()} style={{ padding: '8px 12px' }}>
再試行する🔁
</button>
<a href="/demo-error" style={{ padding: '8px 12px', display: 'inline-block' }}>
安全なページへ戻る🏠
</a>
</div>
<hr style={{ margin: '16px 0' }} />
<details>
<summary>開発中だけ:エラー詳細を見る🧪</summary>
<pre style={{ whiteSpace: 'pre-wrap' }}>{error.message}</pre>
{error.digest && <p>digest: {error.digest}</p>}
</details>
</main>
)
}
補足:本番ではサーバー由来のエラー詳細をそのまま出さない挙動になることがあるよ(情報漏えい防止)🕵️♀️🔒 (Next.js)
3-4) 動作チェック✅🎉
-
ターミナルで
npm run dev🚀 -
ブラウザで
http://localhost:3000/demo-error(成功🙂)http://localhost:3000/demo-error?fail=1(失敗😵→error.tsx表示🧯)
「再試行🔁」を押すと、その区間の再レンダリングを試すよ! (Next.js)
(ただし ?fail=1 のままだと、そりゃまた失敗するよね😂)
4) よくあるハマり🔥あるある3つ
'use client'書き忘れ →error.tsxはClient必須だよ〜!🧡 (Next.js)- どこに置けばいいか迷子 → “その区間だけ守りたい”フォルダの中に置く(例:
app/demo-error/error.tsx)🗺️ (Next.js) - エラー文言を出しすぎ → 本番は詳細を隠す方が安全。必要なら
digestでログと突き合わせるイメージ🧾✨ (Next.js)
5) 練習問題✍️🌸(10〜15分)
-
app/profile/を作って、page.tsxでthrow new Error('プロフィール取得失敗')を入れてみよう😈 -
app/profile/error.tsxを作って、- 「トップへ戻る🏠」
- 「再試行🔁」 を付けよう💖
-
余裕があれば、
detailsの中に 開発中だけerror.messageを表示してみよう🧪✨
まとめ🧁✨
error.tsxは 予期しないエラー 用の“保険画面”🧯 (Next.js)- ルートセグメントの境界として働く(置いたフォルダ配下を守る)🧱 (Next.js)
- Client Component必須で、
errorとreset()を使って「再試行🔁」が作れるよ💖 (Next.js)
次(第85章)で loading.tsx を整えると、「エラーもローディングも可愛い」最強UIになるよ〜!⏳💘