2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsのerror.tsxが拾うエラーと、拾わないエラーの境界線

2
Posted at

背景

Next.js(App Router)で loading.tsx を置くとデータ取得中のローディング表示を自動化できるように、error.tsx を置くとレンダリング中に例外が起きた時の表示を自動化できます。loading.tsx はまだデータが揃っていない状態の話、error.tsx は処理が失敗した状態の話で、扱っている場面自体が別物です。ただ、この error.tsx は「そのフォルダに置けば何でも拾ってくれる」わけではありません。拾えるエラーと拾えないエラーの境界を整理します。

error.tsx の基本形

// app/posts/error.tsx
'use client'; // error.tsx は必ずClient Componentにする必要がある

import { useEffect } from 'react';

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    // エラー内容をログ収集サービスなどに送る想定
    console.error(error);
  }, [error]);

  return (
    <div>
      <h2>何か問題が発生しました</h2>
      <button onClick={() => reset()}>もう一度試す</button>
    </div>
  );
}

ポイントは3つあります。

  1. 'use client' が必須。error.tsx はServer Componentのまま使うことができません。
  2. error と reset の2つを受け取る。error には投げられた例外が入り、digest というプロパティも付いています。これは本番環境でエラーの詳細をそのままクライアントに出さないためのハッシュ値で、サーバー側のログと突き合わせる時の手がかりになります。
  3. reset() はその場所を再レンダリングするだけ。原因になっている処理(例えば壊れたAPIリクエスト)自体が直っていなければ、もう一度同じエラーになります。「もう一度試す」ボタンは、一時的なネットワークエラーのような、直せば直る可能性があるケースのためのものです。

拾えるエラーと拾えないエラー

app/posts/error.tsx を置いた場合、これがカバーするのは 同じフォルダの page.tsx と、その配下 です。ここで例外が起きれば、error.tsx の表示に切り替わります。

一方で、app/posts/layout.tsx で起きたエラーは、同じフォルダの error.tsx では拾えません。error.tsx が作る境界は、同じ階層のlayoutより内側(page側)だけをカバーする形になっているためです。layout側のエラーまで拾いたい場合は、error.tsx を1つ上の階層(親フォルダ)に置く必要があります。

app/
  posts/
    layout.tsx   ← ここのエラーは posts/error.tsx では拾えない
    error.tsx    ← posts/page.tsx 以下のエラーだけを拾う
    page.tsx

さらに、ルート直下の app/layout.tsx で起きたエラーは、通常の error.tsx では一切拾えません。これを拾うには app/global-error.tsx という特別なファイルが必要です。global-error.tsx はルートlayoutごと丸ごと置き換えるものなので、<html> と <body> タグも自分で書く必要があります。

// app/global-error.tsx
'use client';

export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <html>
      <body>
        <h2>致命的なエラーが発生しました</h2>
        <button onClick={() => reset()}>もう一度試す</button>
      </body>
    </html>
  );
}

粒度を分けられるメリット

error.tsx はフォルダ単位で自由に置けるので、機能ごとに分けておくと、ある機能でエラーが起きても他の機能は生きたまま残せます。例えば app/posts/error.tsx と app/settings/error.tsx を別々に用意しておけば、投稿一覧でエラーが起きても、設定画面はいつも通り操作できます。全部をひとつの大きなエラー画面でまとめてしまうより、影響範囲を絞り込める分、ユーザーが困る場面を減らせます。

AIに確認するときの聞き方

エラー処理を含む機能を作ってもらったら、「このフォルダに error.tsx はありますか? layout.tsx とpage.tsxのどちらのエラーまで拾えますか?」と聞いてみると、境界を意識した実装になっているかその場で確認できます。


中上級者には易しすぎる内容かと思いますので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

未経験から一緒に作って公開するまで伴走する講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全20セッションで体系化した教材です。「AIと一緒に学んで、自分の手で作ったものを公開する」体験を最短ルートで届けます。

▶ まず、教材で最初に作るページを見てみる(インストール不要・無料)

▶ 今日から始める(教材付きプラン・月5,500円・いつでも解約OK)

▶ next-ai-camp-trial(体験版・GitHub・無料)

YouTube『AIエンジニア情報局』(AI×開発ニュースを1本5分でキャッチアップできる別運営チャンネル・無料)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?