React 速習チュートリアル

React Router

1. React Routerとは?

React Routerは、Reactアプリケーションにルーティング機能を提供するライブラリです。
ルーティングとは、異なるビュー(画面)間の遷移を処理することを指します。

React RouterはReactアプリケーションにおける標準的なルーティングライブラリであり、以下の機能を可能にします:

  • シングルページアプリケーション(SPA)内での複数ページの作成
  • URLパラメータやクエリ文字列の処理
  • ブラウザ履歴とナビゲーションの管理
  • ネストされたルート(Nested Routes)とレイアウトの作成
  • 認証のための保護されたルートの実装

ルーターがない場合、Reactアプリケーションは単一のページに制限され、異なるビュー間を移動する手段がなくなってしまいます。

2. React Routerのインストール

コマンドラインでプロジェクトのディレクトリに移動し、以下のコマンドを実行してパッケージをインストールします:

npm install react-router-dom

3. BrowserRouterによるアプリケーションのラップ

ルーティングを有効にするには、アプリケーション全体を BrowserRouter コンポーネントでラップする必要があります:

function App() {
  return (
    <BrowserRouter>
      {/* アプリケーションのコンテンツ */}
    </BrowserRouter>
  );
}

4. ビュー(ページ)の作成

ルーティングを実演するために、アプリケーション内に「Home」「About」「Contact」の3つのページ(ビュー)を作成します。
ここでは簡略化のためにすべてのビューを同じファイル内に作成しますが、もちろん別々のファイルに分割することも可能です。

function Home() {
  return <h1>ホーム画面</h1>;
}

function About() {
  return <h1>アバウト画面</h1>;
}

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

5. 基本的なルーティング

React Routerでは、基本的なルーティングに主に3つのコンポーネントを使用します:

  • Link: URLを更新するナビゲーションリンクを作成します
  • Routes: すべてのルート定義を格納するコンテナです
  • Route: URLパスとコンポーネントのマッピングを定義します

各リンクに対応するナビゲーションリンクとルートを追加してみましょう:

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>
  );
}

この例のポイント:

  • BrowserRouter がアプリをラップし、ルーティング機能を有効にします。
  • Link コンポーネントがナビゲーションリンクを作成します。
  • RoutesRoute がルーティングの設定を定義します。

6. ネストされたルート (Nested Routes)

Route の中に別の Route を配置することができ、これを「ネストされたルート」と呼びます。
ネストされたルートを使用すると、新しいURLに移動した際、ページの一部のみを変更し、他の部分は変更や再読み込みをさせないようにできます。これは、ページの中にさらにページがあるような構造です。

上記の例に、Products コンポーネントの中でレンダリングされる2つの新しいコンポーネント CarProductsBikeProducts を追加してみましょう。

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

function Home() {
  return <h1>ホーム画面</h1>;
}

function Products() {
  return (
    <div>
      <h1>製品ページ</h1>
      <nav style={{ marginBottom: '20px' }}>
        <Link to="/products/car">車</Link> |{" "}
        <Link to="/products/bike">バイク</Link>
      </nav> 
      {/* 子ルートのコンテンツがここにレンダリングされる */}
      <Outlet /> 
    </div>
  );
}

function CarProducts() {
  return (
    <div>
      <h2>車</h2>
      <ul>
        <li>アウディ</li>
        <li>BMW</li>
        <li>ボルボ</li>
      </ul>
    </div>
  );
}

function BikeProducts() {
  return (
    <div>
      <h2>バイク</h2>
      <ul>
        <li>ヤマハ</li>
        <li>スズキ</li>
        <li>ホンダ</li>
      </ul>
    </div>
  );
}

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

function App() {
  return (
    <BrowserRouter>
      {/* ナビゲーション */}
      <nav>
        <Link to="/">ホーム</Link> |{" "}
        <Link to="/products">製品情報</Link> |{" "}
        <Link to="/contact">お問い合わせ</Link>
      </nav>

      {/* ルート設定 */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/products" element={<Products />}>
          {/* 子ルートの定義 */}
          <Route path="car" element={<CarProducts />} />
          <Route path="bike" element={<BikeProducts />} />
        </Route>
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </BrowserRouter>
  );
}

この例に関する重要な注意点:

  • Outlet: Products コンポーネント内の <Outlet /> 要素は、子ルートのコンテンツをどこにレンダリングするかを指定します。
  • Routes: Routes 要素内では、CarProductsBikeProducts へのルートが、親である Products ルートの子として含まれています。
  • URL構造: URL構造は親ルートのパスに対して相対的になります。
    • /products/car に移動すると、CarProducts コンポーネントがレンダリングされます。
    • /products/bike に移動すると、BikeProducts コンポーネントがレンダリングされます。

7. アクティブなリンクのスタイリング

Link コンポーネントの特別なバージョンとして、リンクのURLが現在「アクティブ」かどうかを判別できる NavLink があります。
NavLink は特に以下のケースで有用です:

  • ナビゲーションメニュー
  • パンくずリスト
  • タブ

現在のURLが to プロパティと一致する場合、その NavLink はアクティブであると見なされます。これを利用して、アクティブなリンクにスタイルを適用しやすくなります。

import { BrowserRouter, Routes, Route, NavLink } from 'react-router-dom';

// アクティブなリンク用のスタイル関数
const navLinkStyles = ({ isActive }) => ({
  color: isActive ? '#007bff' : '#333',
  textDecoration: isActive ? 'none' : 'underline',
  fontWeight: isActive ? 'bold' : 'normal',
  padding: '5px 10px'
});

function Home() {
  return <h1>ホーム画面</h1>;
}

function About() {
  return <h1>アバウト画面</h1>;
}

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

function App() {
  return (
    <BrowserRouter>
      {/* アクティブ時にスタイルを適用するNavLinkを使用したナビゲーション */}
      <nav style={{ marginBottom: '20px' }}>
        <NavLink to="/" style={navLinkStyles}>ホーム</NavLink> |{" "}
        <NavLink to="/about" style={navLinkStyles}>アバウト</NavLink> |{" "}
        <NavLink to="/contact" style={navLinkStyles}>お問い合わせ</NavLink>
      </nav>

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

8. URLパラメータ

URLパラメータは、ルートパスに追加できる変数です。これらは、コンポーネント間でデータを渡す際によく使用されます。

例えば、パス http://localhost:5173/customer/Tobias において、URLパラメータは Tobias です。
URLパラメータを使用すると、URLの一部が変化する動的なルートを作成できます。URL内の変数のようだと考えると分かりやすいでしょう。

React Routerは、コンポーネント内でこれらのパラメータにアクセスするための useParams フックを提供しています。
以下は、異なる顧客名に対して挨拶を表示するシンプルなページの例です:

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

function Info() {
  // useParamsフックでURLパラメータを取得
  const { firstname } = useParams();
  return <h1>こんにちは、{firstname}さん!</h1>;
}

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/customer/Emil">Emil</Link> | 
        <Link to="/customer/Tobias">Tobias</Link> |
        <Link to="/customer/Linus">Linus</Link>
      </nav>

      <Routes>
        {/* :firstname がURLパラメータとして定義される */}
        <Route path="/customer/:firstname" element={<Info />} />
      </Routes>
    </BrowserRouter>
  );
}

この例のポイント:

  • ルートパス内の :firstname がURLパラメータです。
  • /customer/Emil にアクセスすると、「こんにちは、Emilさん!」と表示されます。
  • /customer/Tobias にアクセスすると、「こんにちは、Tobiasさん!」と表示されます。
  • URLには任意の名前を使用でき、挨拶が機能します! http://localhost:5173/customer/John などを試してみてください。