IT-Q

error.tsx を置いたのに、レイアウトで起きたエラーが拾えませんでした。なぜですか。

error.tsx は同じ階層の layout.tsx の内側に入るからです。layout が外、その中に error、さらに page という順で組み立てられます。境界の外にあるものは受け取れません。

面接官が見ているのは境界の入れ子構造を理解しているか。

これは「あるコンポーネントで例外が出たら、ページ全体が真っ白になりました。どうしますか。」への追撃質問です。

よくある答えと、面談でどう見られるか

  • error.tsx は同じ階層の layout の内側に入るため。拾うには親側に置く
    ファイル規約の入れ子構造を理解できています。ルートレイアウトのエラーだけはどの error.tsx でも届かず、global-error.js を使います。
  • layout はサーバーで実行されるため、エラーバウンダリでは拾えない
    サーバーかどうかではなく、境界の内側か外側かの問題です。page で起きたサーバー側のエラーは、同じ階層の error.tsx で拾えます。
  • error.tsx が Client Component だから
    error.tsx が Client Component である必要があるのは事実ですが、拾えない理由はそこではありません。層の順序の問題です。
  • layout にはエラーバウンダリを当てられない仕様のため
    当てられないのではなく、当たる位置が1つ上になります。アプリ全体のルートレイアウトについては専用の仕組みがあります。

面接官は何を見ているか

  • 同じ階層の layout は境界の外側だと理解している
  • 親側に置く必要があると言えた
  • 階層構造で考えられている

模範解答

error.tsx は、同じ階層の layout.tsx の内側に入るからです。

ファイル規約は入れ子になっていて、layout が外、その中に error、さらにその中に page、という順で組み立てられます。境界の外にあるものは、その境界では捕まえられません。

公式の言い方では、error.js は loading.js・not-found.js・page.js と配下の layout.js を包みますが、同じ階層の layout.js と template.js は包みません。

なので、ある階層の layout で起きたエラーを拾いたければ、1つ上の階層の error.tsx が必要です。アプリ全体のルートレイアウトで起きたエラーには、どの階層の error.tsx も届きません。これを拾うには global-error.js を使います。

実務的には、レイアウトに重い処理やデータ取得を置かないのが先です。落ちたときの影響範囲が最大になる場所だからです。