<CodeLearn/>
React レッスン9

ルーティング

ページ遷移の仕組みを理解しよう

ルーティングとは?

ルーティングは、URLに応じて異なるページ(コンポーネント)を表示する仕組みです。 Reactは標準ではルーティング機能を持っていないため、ライブラリを使います。

代表的なルーティングライブラリには以下があります:

  • React Router — 最も広く使われるルーティングライブラリ
  • Next.js — ファイルベースのルーティング(フレームワーク)
  • TanStack Router — 型安全なルーティング

React Routerの基本セットアップ

React Routerを使った基本的なルーティング設定を見てみましょう。

// インストール: npm install react-router-dom

import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

// ページコンポーネント
function Home() {
  return <h1>ホームページ</h1>;
}

function About() {
  return <h1>概要ページ</h1>;
}

function Contact() {
  return <h1>お問い合わせ</h1>;
}

// ルーティング設定
function App() {
  return (
    <BrowserRouter>
      {/* ナビゲーション */}
      <nav>
        <Link to="/">ホーム</Link>
        <Link to="/about">概要</Link>
        <Link to="/contact">お問い合わせ</Link>
      </nav>

      {/* ルート定義 */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </BrowserRouter>
  );
}

<Link><a> タグの代わりに使います。 ページ全体をリロードせずに、クライアントサイドで遷移します。

動的ルーティングとuseParams

URLにパラメータを含めて、動的なページを作ることができます。useParams で パラメータを取得します。

import {
  BrowserRouter, Routes, Route, Link, useParams
} from "react-router-dom";

// ユーザー一覧ページ
function UserList() {
  const users = [
    { id: 1, name: "田中太郎" },
    { id: 2, name: "鈴木花子" },
    { id: 3, name: "佐藤次郎" },
  ];

  return (
    <div>
      <h1>ユーザー一覧</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            <Link to={`/users/${user.id}`}>{user.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

// ユーザー詳細ページ(動的パラメータ)
function UserDetail() {
  // URLの :userId を取得
  const { userId } = useParams();

  return (
    <div>
      <h1>ユーザー詳細</h1>
      <p>ユーザーID: {userId}</p>
      <Link to="/users">一覧に戻る</Link>
    </div>
  );
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/users" element={<UserList />} />
        {/* :userId は動的パラメータ */}
        <Route path="/users/:userId" element={<UserDetail />} />
      </Routes>
    </BrowserRouter>
  );
}

ネストされたルートとOutlet

ルートをネストすることで、共通レイアウトの中にサブページを表示できます。

import {
  BrowserRouter, Routes, Route, Link, Outlet
} from "react-router-dom";

// 共通レイアウト
function Layout() {
  return (
    <div>
      <header style={{ background: "#333", color: "#fff", padding: "16px" }}>
        <nav style={{ display: "flex", gap: "16px" }}>
          <Link to="/" style={{ color: "#fff" }}>ホーム</Link>
          <Link to="/dashboard" style={{ color: "#fff" }}>ダッシュボード</Link>
          <Link to="/settings" style={{ color: "#fff" }}>設定</Link>
        </nav>
      </header>
      <main style={{ padding: "24px" }}>
        {/* 子ルートのコンポーネントがここに表示される */}
        <Outlet />
      </main>
      <footer style={{ background: "#eee", padding: "16px" }}>
        &copy; 2025 マイアプリ
      </footer>
    </div>
  );
}

// ダッシュボードのサブレイアウト
function DashboardLayout() {
  return (
    <div>
      <h1>ダッシュボード</h1>
      <nav style={{ display: "flex", gap: "12px", marginBottom: "16px" }}>
        <Link to="/dashboard">概要</Link>
        <Link to="/dashboard/analytics">分析</Link>
        <Link to="/dashboard/reports">レポート</Link>
      </nav>
      <Outlet />  {/* サブルートがここに表示 */}
    </div>
  );
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        {/* Layoutで全体を包む */}
        <Route element={<Layout />}>
          <Route path="/" element={<Home />} />
          <Route path="/settings" element={<Settings />} />

          {/* ネストされたルート */}
          <Route path="/dashboard" element={<DashboardLayout />}>
            <Route index element={<DashboardHome />} />
            <Route path="analytics" element={<Analytics />} />
            <Route path="reports" element={<Reports />} />
          </Route>

          {/* 404ページ */}
          <Route path="*" element={<NotFound />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

プログラムでの遷移(useNavigate)

ボタンクリックやフォーム送信後など、コード上からページ遷移させたい場合はuseNavigate を使います。

import { useNavigate } from "react-router-dom";

function LoginForm() {
  const navigate = useNavigate();

  const handleSubmit = async (e) => {
    e.preventDefault();
    // ログイン処理...
    const success = await login(email, password);

    if (success) {
      // ログイン成功 → ダッシュボードに遷移
      navigate("/dashboard");
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* フォーム要素 */}
      <button type="submit">ログイン</button>
    </form>
  );
}

function ProductDetail() {
  const navigate = useNavigate();

  return (
    <div>
      <h1>商品詳細</h1>
      {/* 戻る */}
      <button onClick={() => navigate(-1)}>戻る</button>
      {/* 別ページへ */}
      <button onClick={() => navigate("/cart")}>カートへ</button>
      {/* 置き換え(履歴に残さない) */}
      <button onClick={() => navigate("/home", { replace: true })}>
        ホームへ
      </button>
    </div>
  );
}

Next.jsのファイルベースルーティング

Next.jsでは、ファイルの配置がそのままURLになる「ファイルベースルーティング」を採用しています。 この学習アプリもNext.jsで作られています。

// Next.js App Router のファイル構造
// src/app/
//   page.tsx          → /
//   about/page.tsx    → /about
//   blog/page.tsx     → /blog
//   blog/[slug]/page.tsx → /blog/hello-world(動的ルート)

// --- src/app/page.tsx ---
export default function Home() {
  return <h1>ホームページ</h1>;
}

// --- src/app/blog/[slug]/page.tsx ---
// [slug] が動的パラメータ
export default function BlogPost({ params }) {
  return <h1>記事: {params.slug}</h1>;
}

// --- Next.jsでのリンク ---
import Link from "next/link";

function Navigation() {
  return (
    <nav>
      {/* Next.jsの<Link>コンポーネント */}
      <Link href="/">ホーム</Link>
      <Link href="/about">概要</Link>
      <Link href="/blog/hello-world">記事</Link>
    </nav>
  );
}

// --- プログラムでの遷移 ---
"use client";
import { useRouter } from "next/navigation";

function SearchForm() {
  const router = useRouter();

  const handleSearch = (query) => {
    router.push(`/search?q=${query}`);
  };

  return <button onClick={() => handleSearch("react")}>検索</button>;
}

まとめ

  • React RouterでURLに応じたページ表示を実現
  • <Link> でクライアントサイドの遷移
  • useParams で動的パラメータを取得
  • <Outlet> でネストされたルートを構成
  • useNavigate でプログラムから遷移
  • Next.jsではファイル配置がそのままルーティングになる