コンテンツにスキップ

Chapter 5: ページ間のナビゲーション

ダッシュボードの枠ができたので,利用者が迷わず行き来できるようナビゲーションを仕上げます。App Router の <Link> を使うと,ページを再読み込みせずにスムーズに遷移できるようになります。


この章で身につくこと

  • next/link によるクライアントサイドナビゲーション
  • usePathname() で現在のパスを取得し,アクティブ状態を表現する
  • Next.js が自動で行うコード分割とプリフェッチの仕組みを知る

サイドバーのリンクは現在 <a> タグで記述されています。そのままだとページごとにフルリロードが発生するため,<Link> に置き換えてみましょう。/app/ui/dashboard/nav-links.tsx を開き,next/link を読み込んで差し替えます。

/app/ui/dashboard/nav-links.tsx
import {
  UserGroupIcon,
  HomeIcon,
  DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';

// ...

export default function NavLinks() {
  return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
          <Link
            key={link.name}
            href={link.href}
            className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
          </Link>
        );
      })}
    </>
  );
}

保存してブラウザで確認すると,ページ全体の再読み込みなしで遷移できるようになっているはずです。


Next.js が自動でやってくれること

  • 自動コード分割:ルートごとにバンドルを分けるので,最初のロードで不要なコードを読み込まなくて済みます。
  • プリフェッチ:本番ビルドでは <Link> がビューポートに入った時点でバックグラウンド取得が始まり,クリック時には既にデータが揃っています。
  • 部分的レンダリング:サーバーサイドでレンダリングされる部分とクライアントで動的に差し替わる部分が適切に共存します。

これらのおかげで,Next.js アプリはページ遷移が非常に滑らかに感じられます。


アクティブリンクをハイライトする

現在表示しているページを視覚的に示すには,usePathname() フックでカレントパスを取得し,クラスを出し分けます。フックを使うためにクライアントコンポーネントへ変更しましょう。

/app/ui/dashboard/nav-links.tsx
'use client';

import {
  UserGroupIcon,
  HomeIcon,
  DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';

// ...

export default function NavLinks() {
  const pathname = usePathname();

  return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
          <Link
            key={link.name}
            href={link.href}
            className={clsx(
              'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
              {
                'bg-sky-100 text-blue-600': pathname === link.href,
              },
            )}
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
          </Link>
        );
      })}
    </>
  );
}

clsx を使うことで,現在のパスとリンクの href が一致したときだけクラスを追加できます。保存すると,表示中のページが青くハイライトされているのが確認できます。


ひと息メモ:ナビゲーション設計のコツ

  • ルーティングごとに責務を分離するとテストしやすくなります。
  • URL 構造を先に決めてからフォルダを切ると迷いが少なくなります。

次章ではデータベースと接続し,ダッシュボードに実データを流し込む準備を進めましょう。