Concept

redirect

ユーザーを別の URL へ転送する処理。使う場所によって redirect()(next/navigation)と NextResponse.redirect()(next/server)を使い分ける。

ルーティング認証ナビゲーションnext/navigation

どういう場面で使うか

  • ·認証が必要なページで未認証ユーザーをはじくとき
  • ·ログイン済みユーザーをログインページから弾くとき
  • ·フォーム送信後に別ページへ遷移させるとき
  • ·旧 URL から新 URL への恒久的な転送

注意点 / Pitfalls

  • ·Client Component から redirect() は呼べない。useRouter().push() を使う
  • ·Middleware では redirect()(next/navigation)は使えない。NextResponse.redirect() を返す必要がある
  • ·try/catch の中で redirect() を呼ぶとエラーがキャッチされて動作しない
  • ·redirect() は内部的に例外を throw するため、後続コードは実行されない
  • ·Server Actions 内で redirect() を呼ぶ場合も try/catch の外に出す

何と混同しやすいか

補足

redirect()(next/navigation)は Server Component / layout / Server Action / Route Handler で使う。Middleware は Edge Runtime のため NextResponse.redirect()(next/server)を返す形になる。恒久リダイレクト(308)が必要な場合は permanentRedirect() を使う。Pages Router の redirect とは別物なので注意。

2つのリダイレクト手段

Next.js には用途が異なる 2 つのリダイレクト手段があります。

redirect()NextResponse.redirect()
インポート元next/navigationnext/server
使う場所Server Component / layout / Server Action / Route HandlerMiddleware / Route Handler
動作例外を throw して処理を中断レスポンスオブジェクトを返す
Client Component使えない(useRouter().push() を使う)使えない

redirect()(next/navigation)

Server Component・layout・Server Action・Route Handler で使います。呼び出すと内部的に例外を throw してその場で処理を中断し、HTTP リダイレクトを発行します。

// Server Component での認証チェック
import { redirect } from "next/navigation";
import { cookies } from "next/headers";

export default async function DashboardPage() {
  const cookieStore = await cookies();
  if (!cookieStore.get("session_id")) {
    redirect("/login"); // ここで処理が中断される
  }
  return <Dashboard />;
}
// Server Action での使い方
"use server";
import { redirect } from "next/navigation";

export async function loginAction(formData: FormData) {
  const ok = await authenticate(formData);
  if (!ok) return { error: "認証失敗" };
  redirect("/dashboard"); // try/catch の外で呼ぶ
}

try/catch の外に出す

redirect() は内部で例外を throw します。try/catch の中で呼ぶとその例外がキャッチされてリダイレクトが発動しません。

// ❌ catch されてリダイレクトされない
try {
  redirect("/login");
} catch (e) {
  console.error(e); // NEXT_REDIRECT がここに入る
}

// ✅ try/catch の外で呼ぶ
if (!session) redirect("/login");
try {
  // ... エラーが起きうる処理
} catch (e) {
  return { error: "処理失敗" };
}

NextResponse.redirect()(next/server)

Middleware で使います。NextResponse オブジェクトを返す形で動作し、ルートに到達する前にリダイレクトを発行できます。

// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const session = request.cookies.get("session_id");
  if (!session) {
    return NextResponse.redirect(new URL("/login", request.url));
  }
  return NextResponse.next();
}

Middleware は Edge Runtime で動作するため redirect()(next/navigation)は使えません。NextResponse.redirect()new URL(path, request.url) を渡して絶対 URL を構成します。

Client Component からは useRouter

Client Component ではどちらも使えません。useRouter().push() を使います。

"use client";
import { useRouter } from "next/navigation";

function LogoutButton() {
  const router = useRouter();
  return (
    <button onClick={() => router.push("/login")}>ログアウト</button>
  );
}

認証ユースケースとの対応

認証方式リダイレクト手段理由
Middleware でルート一括保護NextResponse.redirect()Middleware は Edge Runtime のため
Layout 保護(ルートグループ)redirect()(next/navigation)Server Component / layout で動作するため
Server Component 個別確認redirect()(next/navigation)Server Component で動作するため
Server Action 後の遷移redirect()(next/navigation)try/catch の外で呼ぶ
Client Component のボタン操作useRouter().push()クライアントサイドのナビゲーション

permanentRedirect()(恒久リダイレクト)

permanentRedirect()redirect() と同じ場所(Server Component / Server Action / Route Handler)で使えますが、発行する HTTP ステータスが異なります。

redirect()permanentRedirect()
HTTP ステータス307(Temporary Redirect)308(Permanent Redirect)
用途一時的な転送(認証・条件分岐)URL 変更が恒久的な場合(旧 URL の移行)
ブラウザ・検索エンジンキャッシュしないキャッシュする(検索エンジンが index を更新)
import { permanentRedirect } from "next/navigation";

// /old-slug → /new-slug へ恒久移転
export default async function OldSlugPage() {
  permanentRedirect("/new-slug");
}

permanentRedirect() を使う場面:

  • サイトリニューアルで URL が変わったとき(旧 URL からの恒久転送)
  • コンテンツのスラッグを変更して、旧スラッグを恒久的に新スラッグへ転送するとき

redirect() を使うべき場面(permanentRedirect() を使わない):

  • 認証チェックのリダイレクト — セッションが失効しても URL は変わっていないので一時的な転送
  • ログアウト後のリダイレクト — 状態に依存する転送はすべて一時的
  • 308 はブラウザがキャッシュするため、誤って設定すると意図しないループや取り消しの難しいリダイレクトになる

認証方式の選び分け(Middleware / Layout / Server Component)の詳細は → Next.js 認証方式比較

関連ドキュメント

関連サンプル

同じテーマや技術スタックを使った実装例