0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js App Router:layout で redirect する先をその layout の配下に置くと、クライアント遷移で無限ループする

0
Posted at

Next.js の App Router で、layout の中で条件付きの redirect() を書きました。本番で有効にした直後、飛び先のページで GET /…?_rsc=… が 1秒に約8回飛び続け、画面が操作できなくなりました。ユニットテストも、そのページ単体の e2e も通っていました。

構成(ループした形)

app/
  app/
    layout.tsx          ← 二段階認証が未設定なら /app/account/mfa へ redirect
    account/
      mfa/
        page.tsx        ← 登録ページ。これも /app の layout の配下

原因

App Router は、共通の layout をクライアント遷移のたびに作り直しません。ブラウザに残った「redirect を出す layout」が、登録ページの上でも redirect を出し続けます。

middleware でパスをヘッダに入れて「登録ページなら redirect しない」と例外にする方法も試しましたが、layout が再実行されないので、原理的に効きませんでした。

直し方

登録ページを route group に出して、ゲートのある layout の外に置きました。

app/
  (mfa-enrollment)/
    app/account/mfa/page.tsx   ← URL は同じ。layout は別
  app/
    layout.tsx                 ← ゲートはこちらだけ

route group のフォルダ名(かっこ付き)は URL に出ないので、URL を変えずに layout だけを分けられます。

次から気をつけること

  • layout で redirect するときは、飛び先がその layout の外にあるかを必ず確かめる
  • 単体ページの e2e では捕まらない。着地してから5秒間の _rsc リクエスト数を数えるテストにすると捕まえられる
  • 強制の切り替え(全員に必須にする等)は、①すぐ戻すコマンドを手元に用意 ②ログでリクエスト数を見ながら ③自分が操作する直前に入れる

生成AI(Claude Code)に書かせて一人で会社を回している記録を note に書いています。
https://note.com/kaito_cometa

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?