エラーハンドリング

error.js ファイル規約を使用すると、ネストされたルートで予期しないランタイムエラーを適切に処理できます。

  • ルートセグメントとそのネストされた子要素をReactエラーバウンダリで自動的にラップします。
  • ファイルシステム階層を使用して特定のセグメント向けのエラーUIを作成し、細かい制御を可能にします。
  • 影響を受けたセグメントのエラーを隔離しつつ、アプリケーションの他の部分は機能を維持します。
  • ページ全体をリロードせずにエラーからの回復を試みる機能を追加できます。

ルートセグメント内に error.js ファイルを追加し、ReactコンポーネントをエクスポートすることでエラーUIを作成します:

error.js 特殊ファイル
'use client' // エラーコンポーネントはクライアントコンポーネントである必要があります

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>
  )
}
'use client' // エラーコンポーネントはクライアントコンポーネントである必要があります

import { useEffect } from 'react'

export default function Error({ error, reset }) {
  useEffect(() => {
    // エラーをエラー報告サービスに記録
    console.error(error)
  }, [error])

  return (
    <div>
      <h2>問題が発生しました!</h2>
      <button
        onClick={
          // セグメントを再レンダリングして回復を試みる
          () => reset()
        }
      >
        再試行
      </button>
    </div>
  )
}

error.js の動作原理

error.jsの動作
  • error.js はネストされた子セグメントまたは page.js コンポーネントをラップするReactエラーバウンダリを自動的に作成します。
  • error.js からエクスポートされたReactコンポーネントがフォールバックコンポーネントとして使用されます。
  • エラーバウンダリ内でエラーがスローされると、エラーが封じ込められ、フォールバックコンポーネントがレンダリングされます。
  • フォールバックエラーコンポーネントがアクティブな間、エラーバウンダリより上位のレイアウトは状態を維持インタラクティブなままになり、エラーコンポーネントはエラーからの回復機能を表示できます。

エラーからの回復

エラーの原因が一時的な場合もあります。このような場合、単純に再試行することで問題が解決することがあります。

エラーコンポーネントは reset() 関数を使用して、ユーザーにエラーからの回復を試みるよう促すことができます。この関数が実行されると、エラーバウンダリの内容を再レンダリングしようと試みます。成功すると、フォールバックエラーコンポーネントは再レンダリング結果に置き換えられます。

'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <div>
      <h2>問題が発生しました!</h2>
      <button onClick={() => reset()}>再試行</button>
    </div>
  )
}
'use client'

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>問題が発生しました!</h2>
      <button onClick={() => reset()}>再試行</button>
    </div>
  )
}

ネストされたルート

特殊ファイルを通じて作成されたReactコンポーネントは、特定のネスト階層でレンダリングされます。

例えば、layout.jserror.js ファイルの両方を含む2つのセグメントを持つネストされたルートは、次の簡略化されたコンポーネント階層でレンダリングされます:

ネストされたエラーコンポーネント階層

ネストされたコンポーネント階層は、ネストされたルート全体での error.js ファイルの動作に影響を与えます:

  • エラーは最も近い親のエラーバウンダリまでバブルアップします。つまり、error.js ファイルはそのネストされたすべての子セグメントのエラーを処理します。ルートのネストされたフォルダ内の異なるレベルに error.js ファイルを配置することで、より細かいまたは粗いエラーUIを実現できます。
  • error.js バウンダリは、同じセグメント内の layout.js コンポーネントでスローされたエラーを処理しません。これはエラーバウンダリがそのレイアウトコンポーネントの内側にネストされているためです。

レイアウト内のエラー処理

error.js バウンダリは、同じセグメント内の layout.js または template.js コンポーネントでスローされたエラーをキャッチしません。この意図的な階層により、エラー発生時に兄弟ルート間で共有される重要なUI(ナビゲーションなど)が表示され、機能し続けます。

特定のレイアウトやテンプレート内のエラーを処理するには、レイアウトの親セグメントに error.js ファイルを配置します。

ルートレイアウトやテンプレート内のエラーを処理するには、global-error.js というバリエーションの error.js を使用します。

ルートレイアウト内のエラー処理

ルートの app/error.js バウンダリは、ルートの app/layout.js または app/template.js コンポーネントでスローされたエラーをキャッチしません

これらのルートコンポーネント内のエラーを具体的に処理するには、ルート app ディレクトリに配置された app/global-error.js というバリエーションの error.js を使用します。

ルート error.js とは異なり、global-error.js エラーバウンダリはアプリケーション全体をラップし、そのフォールバックコンポーネントはアクティブ時にルートレイアウトを置き換えます。このため、global-error.js は独自の <html> タグと <body> タグを定義する必要があることに注意してください。

global-error.js は最も粒度の粗いエラーUIであり、アプリケーション全体の「包括的」なエラー処理と見なすことができます。ルートコンポーネントは通常あまり動的でないため、これがトリガーされることは少なく、他の error.js バウンダリがほとんどのエラーをキャッチします。

global-error.js が定義されている場合でも、グローバルに共有されるUIやブランディングを含むルートレイアウト内でレンダリングされるフォールバックコンポーネントを持つルート error.js を定義することをお勧めします。

'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>
  )
}
'use client'

export default function GlobalError({ error, reset }) {
  return (
    <html>
      <body>
        <h2>問題が発生しました!</h2>
        <button onClick={() => reset()}>再試行</button>
      </body>
    </html>
  )
}

サーバーエラーの処理

サーバーコンポーネント内でエラーがスローされると、Next.jsは Error オブジェクト(本番環境では機密性の高いエラー情報が削除されます)を最も近い error.js ファイルに error プロップとして転送します。

機密性の高いエラー情報の保護

本番環境では、クライアントに転送される Error オブジェクトには一般的な message プロパティと digest プロパティのみが含まれます。

これは、エラーに含まれる潜在的に機密性の高い詳細がクライアントに漏れるのを防ぐためのセキュリティ対策です。

message プロパティにはエラーに関する一般的なメッセージが含まれ、digest プロパティにはサーバーサイドログで対応するエラーと一致させるために使用できる自動生成されたハッシュが含まれます。

開発中は、デバッグを容易にするために、クライアントに転送される Error オブジェクトには元のエラーの message がシリアル化されて含まれます。