エラーハンドリング

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 ファイルを配置します。

ルートレイアウトまたはテンプレート内のエラーを処理するには、error.js のバリエーションである global-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>
  )
}

知っておくと便利:

  • global-error.js は本番環境でのみ有効です。開発時にはエラーオーバーレイが表示されます。

サーバーエラーの処理

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

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

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

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

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

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