ホーム

Next.js App Routerのエラーハンドリングを理解する

作成日: 2023-8-19

更新日: 2023-9-28

Next.js App Routerのエラーハンドリングを理解する

この記事を読んだ後に理解できること


  • Next.js App Routerでのエラーハンドリング方法
  • React18のReact Error Boundaryの理解


Next.js App Routerでのエラーハンドリングの方法


Next.jsのApp Routerでは、エラー発生時のUIを表現できるerror.jsというファイルが存在します。

error.js はURLごとに異なるUIのエラー画面を用意できるので、柔軟性もあります。

また、リロードなどによらずエラーから回復させる機能も持っています。

error.jsはReact18のReact Error Boundaryをベースにした機能です。

React Error Boundaryの挙動について解説します。

ベースとなるReact18のReact Error Boundaryを理解する


Next.jsのApp Routerで使えるerror.jsは、React18で導入されたReact Error Boundary をベースに作られています。

React Error Boundary の概要についても解説しておきます。

React Error Boundaryとは


React Error Boundary とは、Reactアプリケーションでレンダリング中にエラーが発生した際に、エラーメッセージやfallbackのUIを表示するための特別なコンポーネントです。

デフォルトでは、エラーが発生すると、Reactはエラーを含むUIを画面から削除しますが、エラーバウンダリーを使用することでこれを防ぐことができます。

React Error Boundaryの使い方


エラーが発生する可能性のあるコンポーネントをError Boundaryコンポーネントでラップするだけです。

<ErrorBoundary fallback={<p>エラーが発生しました</p>}>
  <ArticleList />
</ErrorBoundary>

error.jsの使い方


具体的にerror.jsの使い方について解説します。

error.jsの基本的な使い方


まずは、エラーが発生する可能性のあるページのディレクトリにerror.jsを追加します。

├── app
│   ├── admin
│   │   ├── layout.tsx
│   │   ├── error.tsx // 追加する
│   │   ├── page.tsx


error.jsClient Componentsでしか使うことができないので、use clientをファイルの先頭につける必要があります。

'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <h2>{ error.message }</h2>
      <button onClick={() => reset()}>再レンダリングする</button>
    </div>
  )
}


error.jsでは、Errorオブジェクトとreset()を引数に取ることができます。

Errorオブジェクトには、page.jsもしくはその子コンポーネントで発生したErrorオブジェクトが入っています。

reset()関数は、エラーが発生しているコンポーネントの再レンダリングを実行してくれます。

error.jsを使う上での注意点


  • error.jsは、同じ階層にあるlauout.js もしくはtemplate.js でのエラーをキャッチすることができない


<ErrorBoundary>コンポーネントがlayout.jsもしくはtemplate.jsにラップされているためです。
さらに上の階層にあるerror.jsであればエラーをキャッチすることができます。

イメージ的には以下のようになっています。

<layout>
  <ErrorBoundary>
    <Page />
  </ErrorBoundary>
</layout>


- Root Layoutsのlayout.jsもしくは template.jsのエラーをキャッチするためには、global-error.jsを配置する必要がある

以下のディレクトリ構成におけるapp/layout.js(appディレクトリ直下にある)のエラーはerror.jsでエラーをキャッチできません。

├── src
│   └── app
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx
│       ├── page.tsx


もし、app/layout.js で発生したエラーをキャッチさせたい場合は、app/global-error.jsを配置する必要があります。

global-error.jsを配置する場合、<html><body>タグをそのファイルに必ず含める 必要があります。

// app/global-error.tsx

'use client'

export default function GlobalError({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <html>
      <body>
        <h2>{ error.message }</h2>
        <button onClick={() => reset()}>再レンダリングする</button>
      </body>
    </html>
  )
}


さいごに


error.js は全てのディレクトリに配置する必要はありません。

エラーの発生する可能性のあるページでのみ使うことが適切だと公式ドキュメントにも書かれているので、利用は必要な箇所のみにしましょう。