React Router DOMとは?初心者にわかりやすい導入手順と実践例

Reactでアプリケーションを作る際、画面遷移をどうやって実装すればいいかと迷う方は多いかもしれません。

そのときに頼りになるのが React Router DOM ですね。

WebブラウザでURLが変わったタイミングに合わせてコンポーネントを切り替えたり、ユーザーがリンクをクリックしたら特定のページに移動したりできます。

これによって シングルページアプリケーション を構築しながら、複数ページのような使い勝手を実現することができるでしょう。

例えば、商品の一覧ページや詳細ページをURLのパラメータを元に切り替える場面を想像してみてください。

従来ならサーバー側へページごとにリクエストしていました。

しかしReact Router DOMを使うと、クライアント側だけで異なるページのような見え方を作れるのです。

一度読み込んだアプリケーションを都度再読み込みしないため、ユーザー体験が快適になるでしょう。

また、React Router DOMは公式ドキュメントも充実していますが、初心者の方がいきなり公式の情報を読んでも難しく感じるかもしれません。

ここでは実務で考えられるシーンと結びつけながら、最新バージョンを念頭に置いて基本的な使い方を順番に紹介します。

分かりやすいコード例を添えて解説しますので、皆さんのReact開発に役立つと嬉しいですね。

なぜReact Router DOMが必要とされるのか

Reactのコンポーネント単位の開発スタイルは、UIを組み立てるうえでとても扱いやすいですね。

しかし、URLによる画面遷移の管理まで考えると、独自実装でルーターを作るのは手間がかかります。

例えばボタンを押したらURLを変更し、さらに表示するコンポーネントを切り替えるロジックを自前で管理するとなると、実装箇所が増えて複雑になるかもしれません。

一方、React Router DOMを使えば、あらかじめ用意されたルーティング機能があるのでURLごとのコンポーネントを定義しやすいです。

これにより「どのURLでどのコンポーネントを出すか」というルールを設定するだけで、アプリケーション全体の画面遷移を管理できるでしょう。

また、実務で開発していると、ページが増えたりURL構成が変わったりするケースが少なくないですね。

React Router DOMの場合は設定ファイルやRoutesコンポーネントを編集するだけで、画面遷移の変更ができる点もメリットとなります。

結果的に保守性を高められるでしょう。

さらに、ユーザーにとってはページの再読み込みなしに高速に画面が切り替わるので、スムーズな体験が生まれます。

こうした理由から、Reactアプリケーションで開発する場合はReact Router DOMの導入が一般的になっているのです。

React Router DOMの導入手順と基本的な仕組み

まずReactプロジェクトを作成して、そこにReact Router DOMを追加します。

一般的な導入方法としては、npmやyarnなどのパッケージマネージャーを使います。

下記はnpmの例です。

npm install react-router-dom

インストールが完了したら、アプリケーションのエントリーポイント付近でルーターを用意します。

簡単なサンプルコードを見てみましょう。

import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

皆さんは上記のコードで、特定のURLパスに対して表示するコンポーネントを設定できますね。

BrowserRouter はHTML5のHistory APIを使ってURLを管理し、Routes コンポーネントは子要素として Route のリストを持ちます。

Route コンポーネントの path プロパティでパスを指定し、element プロパティで表示するコンポーネントを関連付けています。

例えば / なら <Home /> を表示し、/about なら <About /> を表示するわけです。

従来のリンク要素と同じように <a> タグを書いてしまうとページ全体がリロードされてしまうので、React Router DOMの <Link> を使うようにしましょう。

リンクやナビゲーションの基本的な使い方

ページ間の移動には Link コンポーネントが便利ですね。

React Router DOMには以下のようなLinkをサポートするコンポーネントがあります。

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

function Navigation() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
    </nav>
  );
}

export default Navigation;

Link をクリックするとURLが変化し、そのURLに紐付けたコンポーネントが表示される仕組みです。

これによりページ全体の再読み込みを行わず、アプリケーション上で画面が切り替わるようになります。

実務ではヘッダーやサイドバーなどに複数の Link をまとめることが多いですね。

ナビゲーション要素を作ることで利用者が複数ページを意識しやすくなり、UXが向上するでしょう。

また、選択中のメニューをハイライトしたい場合は、 NavLink コンポーネントを使う方法もあります。

NavLink は現在アクティブなパスかどうかを判断して、自動でCSSクラスを付与してくれるので便利です。

こうした小さな工夫は、アプリケーションの見栄えと使いやすさに影響してくるでしょう。

URLパラメータで動的な画面を作る方法

React Router DOMでは、URLの一部をパラメータとして扱うことができます。

例えば、ユーザー詳細ページや商品詳細ページなど、IDごとに表示内容が変わるケースを考えてみましょう。

ルーティングは次のように定義します。

import { BrowserRouter, Routes, Route } from "react-router-dom";
import UserDetail from "./pages/UserDetail";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/users/:userId" element={<UserDetail />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

/users/:userId のようにコロンで始まる部分がURLパラメータの領域です。

このルートにアクセスがあった場合、React Router DOMは userId の値を取り出して UserDetail コンポーネントに渡せるようにしてくれます。

実際にパラメータを受け取る際は、 useParams フックを利用します。

import React from "react";
import { useParams } from "react-router-dom";

function UserDetail() {
  const { userId } = useParams();

  return (
    <div>
      <h2>ユーザー詳細</h2>
      <p>ユーザーID: {userId}</p>
    </div>
  );
}

export default UserDetail;

これで userId には /users/123 の場合であれば 123 という文字列が取得できますね。

皆さんはこれを使って、サーバーAPIからユーザー情報を取得し、ユーザー名やプロフィール画像を表示するといった仕組みを構築できます。

URLによって内容を切り替える場合、このURLパラメータはとても便利です。

例えばECサイトの構築でも、商品IDをパラメータにして商品詳細を出したりします。

実務上はこの値を用いて非同期通信を行い、データベースから該当ユーザーや商品を検索して画面に出す流れが一般的となるでしょう。

ネストされたルートの活用

大きなアプリケーションだと、ページレイアウトやメニューが固定であり、その中身だけ切り替えたいことも多いですね。

そういった場合に便利なのが ネストされたルート です。

ネストとは、あるRouteの内側にさらにRouteを定義し、共通レイアウトの下で子コンポーネントを切り替える手法です。

以下はイメージ例です。

import { BrowserRouter, Routes, Route } from "react-router-dom";
import Layout from "./components/Layout";
import UsersList from "./pages/UsersList";
import UserDetail from "./pages/UserDetail";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/users" element={<Layout />}>
          <Route index element={<UsersList />} />
          <Route path=":userId" element={<UserDetail />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

export default App;

ここで Layout コンポーネントの中に、ネストされた子コンポーネントを表示する領域を作る必要があります。

Layout の中では Outlet コンポーネントを使いましょう。

import React from "react";
import { Outlet } from "react-router-dom";

function Layout() {
  return (
    <div>
      <h1>ユーザー関連の画面</h1>
      <Outlet />
    </div>
  );
}

export default Layout;

これで /users へアクセスすれば <Layout> が表示され、さらに Outlet の部分に <UsersList> が表示されます。

/users/123 のようにID付きのURLだと、同じレイアウトの中の Outlet<UserDetail> が表示されますね。

例えば「共通のヘッダーやメニューを使いつつ、メイン部分だけ変えたい」というようなシーンにとても便利です。

大規模プロジェクトでビューがどんどん増えてきても、ルートをネストして管理すると全体像をつかみやすくなるでしょう。

useNavigateフックを使ったプログラム的な画面遷移

リンクをクリックして移動するだけでなく、フォーム送信後に指定のURLへ遷移したい場面や、処理が終わったらあるページに戻すようなシナリオも考えられます。

そういった場合に便利なのが useNavigate フックです。

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

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

  const handleCreate = () => {
    // ここで新規ユーザー作成処理を行うイメージ
    // 成功したら一覧ページに戻る
    navigate("/users");
  };

  return (
    <div>
      <h2>ユーザー作成</h2>
      <button onClick={handleCreate}>作成</button>
    </div>
  );
}

export default CreateUser;

useNavigate は遷移先のURLや履歴操作をプログラム的に行えます。

上の例ではボタンを押すと navigate("/users") を呼び出し、ユーザー一覧へ移動させる仕組みです。

これによってフォームやAPI通信など、ユーザーの操作内容に応じて柔軟に画面を切り替えられます。

例えばログイン画面を作り、ログイン成功時にダッシュボードへ飛ばすなど、実務で頻繁に使われるケースが多いでしょう。

特定のページにだけアクセス制限をかけるには

管理者向けのページや、認証が必要なページを作る場合は、そのページにアクセスする前にログインのチェックを行いたいですよね。

そうした 認証付きルート を作る手法の一例を見てみましょう。

import { BrowserRouter, Routes, Route } from "react-router-dom";
import ProtectedRoute from "./components/ProtectedRoute";
import AdminDashboard from "./pages/AdminDashboard";
import Login from "./pages/Login";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route
          path="/admin"
          element={
            <ProtectedRoute>
              <AdminDashboard />
            </ProtectedRoute>
          }
        />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

ここで利用している ProtectedRoute はカスタムコンポーネントです。

ユーザーの認証状態を確認して、ログインしていない場合はログイン画面へリダイレクトするなどのロジックを入れます。

import React from "react";
import { Navigate } from "react-router-dom";

function ProtectedRoute({ children }) {
  const isAuthenticated = checkAuth(); // 認証状態を確認する関数

  if (!isAuthenticated) {
    return <Navigate to="/login" />;
  }

  return children;
}

export default ProtectedRoute;

これで /admin にアクセスが来ても、ログインしていない場合は /login に飛ばすという動作ができます。

実務のシステムであればトークンチェックやCookieの確認を行い、サーバー側に問い合わせる処理などが含まれるでしょう。

ただ、基本的なアイデアとしては「ルートコンポーネント内で認証チェックを行い、アクセスを制限する」流れが多いですね。

ユーザーが誤って直接URLを打ち込んでも、ログインなしには管理画面を見られないようにできます。

コード分割と遅延ロードの考え方

アプリが大きくなると、すべてのコンポーネントをまとめて読み込むと初期表示に時間がかかる場合があります。

そこで、利用していない画面は後から読み込む コード分割 (lazy loading) が有用です。

React Router DOMでは以下のように書けます。

import React, { lazy, Suspense } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

export default App;

lazy を使ってコンポーネントを動的に読み込むと、About を実際に使うタイミングで初めてJSファイルがロードされるようになります。

ユーザーが /about にアクセスしなければ、不要なコードを取得しなくて済むので初期表示のパフォーマンスが改善されるでしょう。

特にSPA(シングルページアプリケーション)の場合、画面が増えるほどJavaScriptのバンドルサイズが大きくなりやすいですね。

そのためReact Router DOMを使いながら、必要に応じてコード分割も考えてみると効率的でしょう。

実務で役立つ画面遷移のパターン例

React Router DOMを使うと、さまざまな画面遷移のパターンを柔軟に実装できます。

ここでは一般的な例を挙げてみましょう。

一覧ページと詳細ページ 商品一覧やユーザー一覧などを /list に配置し、アイテムをクリックしたら /list/123 のように詳細画面を表示します。

検索結果と絞り込み URLクエリを使って検索キーワードを保持しながら、絞り込み条件を変化させる方法も便利です。

React Router DOMではクエリパラメータを直接扱う機能はありませんが、URLSearchParamsを利用することで似たようなことを実現しやすいですね。

ウィザード形式のステップ遷移 会員登録や予約手続きを、複数ステップに分けて実装する場合があります。

/register/step1/register/step2/register/step3 のように画面ごとに分割して、前後の操作をしやすくすることが多いですね。

ステップ数が増えてもルーティング設定で管理できるため、保守しやすい構成になります。

モーダルを使った遷移 URLの変更を伴わずにモーダルウィンドウで別ページを表示するUXもありますが、URLと連動させることも可能です。

例えば /photos で一覧を表示し、サムネイルをクリックするとモーダルが出つつURLが /photos/123 に切り替わるようなイメージです。

ブラウザの戻るボタンで閉じる挙動を実現するために、ルーティングとモーダルの管理を組み合わせます。

こういったパターンをうまく活用すると、洗練されたアプリケーションを構築しやすいですね。

実務での注意点とおすすめの整理方法

実務でReact Router DOMを活用する際は、以下のようなポイントを意識するとよいでしょう。

ルーティング設定を一箇所でまとめる

すべてのルート定義を App.jsx や専用の routes.js にまとめると可読性が上がります。

ルート構造を定期的に見直す

開発が進むとURLが増えてくるので、階層が深くなっていないかチェックしてみてください。

コンポーネント名とURL名の対応関係をわかりやすく

実務チームで作業する場合、「このURLで表示されるコンポーネントはどれか」を即座に判断しやすいように工夫するといいでしょう。

アクセス制限やエラーページも考慮

認証状態を管理するコンポーネントや、存在しないURLにアクセスされた場合に表示する404ページをきちんと準備しておくと、利用者にとっても安心感があるでしょう。

また、チーム開発ではドキュメント化も大切ですね。

「どのURLがどの画面を表示するのか」「ネストしたルート構造はどうなっているか」を共有しておくと、後々の変更時に混乱しにくくなるでしょう。

まとめ:React Router DOMでの学習ポイントと次のステップ

React Router DOMは、Reactアプリケーションでページ遷移を管理するうえで欠かせないライブラリとなっています。

今回ご紹介したように、URLパラメータやネストされたルート、プログラム的な画面遷移など、多彩な機能が用意されていますね。

いずれも実務で頻繁に登場するシーンばかりであり、慣れると「どんなルーティング構造でも対応できる」と感じられるようになるでしょう。

皆さんのプロジェクトで「URLごとに表示を切り替える必要があるけど、どう実装しようか」と迷ったときは、まずReact Router DOMの仕組みを思い出してください。

そして、見通しのよいルート構成を組み立てれば、利用者にとってもわかりやすいアプリケーションになるでしょう。

React Router DOMは最新バージョンを使うと機能面が整理されており、スッキリした書き方ができます。 もし過去のソースコード例と書き方が違う場合があっても、最新の公式ドキュメントをチェックして差異を確認するのがおすすめです。

最初は小規模なアプリでルーティングを試してみると理解しやすいです。 画面数が少なくても、URL管理やネストされたルート、アクセス制限などを順番に試して、実装の流れをつかんでみましょう。

今後、モバイルアプリやSSR(Server-Side Rendering)など異なる環境でReactを使用する場合でも、ルーティングの考え方が土台になります。

React Router DOMで基礎を押さえておくと、プロジェクトの要件に合わせて柔軟に対応できるようになるでしょう。

Reactをマスターしよう

この記事で学んだReactの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。