Skip to content

next/router と next/navigation の違い

問題の説明

Next.jsではnext/routernext/navigationの両パッケージにuseRouter()フックが存在しますが、返されるオブジェクトが異なります。なぜ同じフック名でありながら、2つの異なるルーティングパッケージが存在するのでしょうか?この違いを理解しないと、以下のエラーが発生する可能性があります:

sh
Error: NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted

この問題の核心は、Next.js 13で導入された新しいルーティングシステム「App Router」と、従来の「Pages Router」のアーキテクチャの違いにあります。

根本的な違い

next/router (Pages Router向け)

  • 使用場所: /pages ディレクトリ構造のプロジェクト
  • 目的: クライアントサイドナビゲーションを主体とした従来型ルーティング
  • 特徴:
    • Next.js v12以前から存在するレガシーシステム
    • クライアントコンポーネントに特化
    • 比較的単純なルーティングニーズに対応

next/navigation (App Router向け)

  • 使用場所: /app ディレクトリ構造のプロジェクト (Next.js v13以上)
  • 目的: サーバーサイドレンダリングを完全サポートした最新ルーティング
  • 特徴:
    • useRouter, redirect, notFound などの関数を提供
    • サーバーコンポーネントとクライアントコンポーネントの両方をサポート
    • 自動コード分割や高度なレイアウト管理を実現

Next.jsのプロジェクト構造

Next.jsは2つのルーティングモードを並行サポート:

  • /pages ディレクトリ → Pages Router (next/router)
  • /app ディレクトリ → App Router (next/navigation)

実際の使い分け

Pages Router の場合 (pages/ ディレクトリ)

jsx
// pages/home.js
import { useRouter } from 'next/router';

export default function HomePage() {
  const router = useRouter();
  
  const handleClick = () => {
    router.push('/about'); // ページ遷移
  };

  return (
    <button onClick={handleClick}>
      Aboutページへ移動
    </button>
  );
}

App Router の場合 (app/ ディレクトリ)

jsx
// app/home/page.js
'use client'; // クライアントコンポーネント指定
import { useRouter } from 'next/navigation';

export default function HomePage() {
  const router = useRouter();
  
  const handleClick = () => {
    router.push('/about'); // ページ遷移
  };

  return (
    <button onClick={handleClick}>
      Aboutページへ移動
    </button>
  );
}

重要

App Router プロジェクトでnext/routerを使用すると、致命的なエラーが発生:

sh
Error: NextRouter was not mounted.

公式ドキュメントで解決法を確認:
https://nextjs.org/docs/messages/next-router-not-mounted

主な機能比較

機能next/router (Pages Router)next/navigation (App Router)
データ取得getServerSidePropsなどサーバーコンポーネント内で直接実装
エラー処理カスタムErrorページnotFound()関数で動的制御可能
リダイレクトクライアントサイド限定サーバーサイドでのリダイレクト対応
ルーティング基本ナビゲーション機能高度な並行ルーティング機能搭載
将来性新機能追加未定最新機能の優先実装対象

移行ガイド

Pages RouterからApp Routerに移行する場合:

  1. next/routernext/navigation にインポート元を変更
  2. /pages ディレクトリのファイルを /app 構造に変換
  3. getServerSideProps などのデータ取得方法をサーバーコンポーネントパターンに移行
  4. 動的ルーティングパラメータの取得方法を router.queryparams オブジェクトに変更
jsx
// app/blog/[slug]/page.js
export default function BlogPage({ params }) {
  const { slug } = params; // URLパラメータ直接取得
  
  return <h1>{slug}の記事</h1>;
}

ベストプラクティス

  1. 新規プロジェクトでは常にApp Routerを採用: /appディレクトリ構成で開始しnext/navigationを使用
  2. 既存プロジェクト: Pages Routerが機能している場合作成しない
  3. 混在時の注意: 同一プロジェクトで両方使用可能が、コード管理が複雑化
  4. サーバーコンポーネント: next/navigation使用時にサーバーサイド処理を最大限活用可能
jsx
// app/admin/page.js
import { redirect } from 'next/navigation';

export default async function AdminPage() {
  const user = await getCurrentUser();
  
  if (!user.isAdmin) {
    redirect('/login'); // サーバー側でリダイレクト
  }

  return <AdminDashboard />;
}

結論

next/routernext/navigation の選択はプロジェクト構造で決定

  • /pages ディレクトリを使用 → next/router
  • /app ディレクトリを使用 (Next.js v13以降) → next/navigation

App RouterはReact 18のサーバーコンポーネント機能を基盤とし、パフォーマンス最適化や高度なルーティング制御が可能です。新しいプロジェクトはApp Routerを採用し、next/navigationを利用することで、Next.jsの最新機能を最大限活用できます。