⚠️

Next.jsのエラー画面が簡単&柔軟

2024/08/03に公開

Webアプリケーションの開発にかかせないエラー画面ですが、Next.jsでは簡単かつ柔軟に対応することができます。今回はそんなNext.jsのエラー画面表示の解説をします。また、ムーザルちゃんねるのYouTubeに解説した動画の公開もしています。動画ではより詳細に、記事では内容をすぐ把握できるよう簡易にしています。

https://youtu.be/Jh7j9dusDUI

Next.jsのエラーハンドリング挙動

Next.jsでは予期せぬエラー(例外)が発生したら自動でキャッチしてくれます。具体的に言うと、 error.tsx というエラーコンポーネントを配置すると、自動でそのコンポーネントがレンダリングされます。


例外があると、error.tsxが表示される

ネストしたエラー表示

error.tsx はどこの階層にも配置することができます。そして複数 error.tsx がある場合、エラーが発生したページコンポーネントからディレクトリの上方向に見て、最も近い位置にある error.tsx が採用されます。


一番近いerror.tsxが採用される

また、レンダリングされた error.tsx よりも上の階層にあるレイアウトは再レンダリングされません。これを利用することでエラー表示を部分的にすることができます。以下の例を見てください。

トップレベルのerror.tsx 同じ階層のerror.tsx

最初のものはエラーが発生したら画面全体にエラーメッセージが表示されます。もう一つは、部分的にエラーメッセージが表示されます。このようにレンダリングされた error.tsx のディレクトリ位置と layout.tsx の位置によって、レンダリング結果が異なります。

NotFoundの扱い

Next.jsではNotFoundもエラーと同様に not-found.tsx ファイルが自動に表示されます。

この not-found.tsx もネストすることができます。


指定ユーザが存在しないときの表示例。詳細のコンポーネント部分だけエラーにしている

おまけ:ユーザに不利益を与えないエラー対応

例えばユーザがフォームにテキストを入力してサブミットをしたとします。何かが原因で例外が発生しました。error.tsx でキャッチされエラー表示が適切にされました。しかし、ユーザがさっきまで入力していたテキストは消えてしまいました…。

こんな経験、一度くらいはあるんじゃないでしょうか。すぐに再入力できる内容ならちょっとしたストレスで済みますが、長文を入力していたとしたら悲しくてユーザは離脱してしまうでしょう。そこで、ユーザに不利益を与えない形でエラーを表示する工夫が必要です。

ここでのアプローチは大きく2つあります。

  1. error.tsx にキャッチさせない
  2. 入力内容をキャッシュさせる

1. error.tsx にキャッチさせない

Next.js(AppRouter)では一般的にフォーム入力のサブミットにはServer Actionsを使います。Server Actions内部で例外が発生した時に、例外を無視するのではなく try..catch で囲み、問題があれば error.tsx ではなく自前でエラーハンドリングすることです。

export async function submit(formData: FormData) {
  try {
    // DBへの登録などの処理を行う
  } catch(error) {
    return { ok: false }
  }
  return { ok: true }
}

こうすればフォームの画面はそのままでServer Actionsの結果を受け取ってエラーメッセージを表示するようにすれば入力内容は失われません。もしくは例外を投げないようなライブラリの選定をするというのも一つの手です。

2. 入力内容をキャッシュさせる

これはGitHubなどでも採用されている手法です。ユーザが入力した内容を逐次ブラウザのSessionStorageに保存します。これを行うと、エラー時だけでなく、ページを再読込したり、他のページに遷移したあとでも入力内容を復元することができます。素晴らしいですね。

この仕組みはライブラリとして公開されているので誰でも使うことができます。

どちらの手法を使うか、あるいはそもそも考慮するかどうかは要件次第なのであなたのプロジェクトに合った方法を選択してください。

ムーザルちゃんねる

Discussion