React Router v7 とは?URLで画面を切り替える仕組みをやさしく解説

react icon
React

こんにちは、とまだです。

Reactでアプリを作っていて、「複数の画面を切り替えたいけど、どうすればいいんだろう」と悩んだことはありませんか?

実は、Webアプリの画面遷移は「本のページをめくる」ような仕組みで実現できるんです。

今回は、React Router v7を使ったルーティングについて解説します。

React Router v7 とは?

簡単に言うと、React Router v7は「URLの住所」で「表示する画面」を切り替える仕組みです。

たとえば、本屋さんを想像してみてください。

1階が小説コーナー、2階が技術書コーナー、3階がカフェ。 階数(URL)を変えると、見える景色(画面)が変わります。

React Router v7も同じです。 /homeなら自己紹介画面、/worksなら作品一覧画面というように。 URLを変えると、表示される内容が切り替わります。

しかも、エレベーターのようにスムーズに移動できます。 ページ全体を読み込み直すことなく、必要な部分だけを切り替えるんです。

なぜReact Routerが必要なのか

Reactだけでアプリを作ると、すべてが1つの画面に詰め込まれがちです。

まるで、1つの部屋にリビングもキッチンも寝室も全部詰め込んだような状態。 これでは使いづらいですよね。

そこでReact Routerの出番です。

部屋を分けるように、機能ごとに画面を分割できます。 ユーザーはURLを見るだけで「今どこにいるか」がわかります。 ブラウザの戻るボタンも自然に動作します。

基本的な使い方

それでは、実際にReact Router v7を使ってみましょう。

インストールと初期設定

まずは必要なパッケージをインストールします。

npm install react-router-dom

次に、アプリの入り口でルーターを設定します。

import React from "react";
import ReactDOM from "react-dom/client";
import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";
import HomePage from "./HomePage";
import AboutPage from "./AboutPage";

// ルートの設定(住所と部屋の対応表)
const router = createBrowserRouter([
  {
    path: "/",
    element: <HomePage />,
  },
  {
    path: "/about",
    element: <AboutPage />,
  },
]);

// アプリの起動
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <RouterProvider router={router} />
);

このコードは「住所録」を作っているようなものです。 /という住所にはHomePageコンポーネント。 /aboutという住所にはAboutPageコンポーネント。

これで基本的なルーティングは完成です。

ページ間の移動

ページ間を移動するには、Linkコンポーネントを使います。

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

function Navigation() {
  return (
    <nav>
      <Link to="/">ホーム</Link>
      <Link to="/about">自己紹介</Link>
    </nav>
  );
}

Linkは通常のHTMLの<a>タグと似ています。 違いは、ページ全体をリロードせずに画面を切り替えること。 まさに、エレベーターで階を移動するような感覚です。

ネストされたルート(入れ子構造)

実際のアプリでは、画面の一部だけを切り替えたい場合があります。

たとえば、ブログサイトを考えてみましょう。 記事一覧は同じレイアウトで、記事の内容だけが変わる。 こんなときに便利なのが、ネストされたルートです。

const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    children: [
      {
        path: "",
        element: <HomePage />,
      },
      {
        path: "blog",
        element: <BlogLayout />,
        children: [
          {
            path: "",
            element: <BlogList />,
          },
          {
            path: ":id",
            element: <BlogPost />,
          },
        ],
      },
    ],
  },
]);

これは、マンションの構造に似ています。 建物全体(Layout)があって、その中に各フロア(BlogLayout)。 さらにその中に個別の部屋(BlogPost)がある感じです。

親コンポーネントでは<Outlet />を使って、子の表示位置を指定します。

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

function Layout() {
  return (
    <div>
      <header>共通ヘッダー</header>
      <main>
        <Outlet /> {/* ここに子ルートの内容が表示される */}
      </main>
      <footer>共通フッター</footer>
    </div>
  );
}

動的なURL(パラメータ)

ユーザーIDや記事IDなど、URLに変数を含めたい場合があります。 React Routerでは:idのような記法で実現できます。

{
  path: "/users/:id",
  element: <UserProfile />,
}

この:id部分は、実際のアクセス時に数値や文字列に置き換わります。 /users/123にアクセスすると、id123が入ります。

コンポーネント側ではuseParamsフックで値を取得します。

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

function UserProfile() {
  const { id } = useParams();

  return (
    <div>
      <h1>ユーザーID: {id}のプロフィール</h1>
    </div>
  );
}

まるで、ホテルの部屋番号のようですね。 同じ構造の部屋でも、番号(ID)によって中身が変わります。

APIとの連携

実際のアプリでは、URLパラメータを使ってデータを取得することが多いです。

以下は、ユーザー情報を外部APIから取得する例です。

import { useParams } from "react-router-dom";
import { useState, useEffect } from "react";

function UserProfile() {
  const { id } = useParams();
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // APIからデータを取得
    fetch(`/api/users/${id}`)
      .then(res => res.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      });
  }, [id]);

  if (loading) {
    return <div>読み込み中...</div>;
  }

  return (
    <div>
      <h1>{user.name}さんのプロフィール</h1>
      <p>メール: {user.email}</p>
    </div>
  );
}

URLが変わるたびに、自動的に新しいデータを取得します。 まるで、チャンネルを変えるとテレビの内容が切り替わるような感じです。

認証が必要なページの保護

会員限定ページなど、ログインが必要な画面もあります。 React Routerでは、条件に応じてリダイレクトする仕組みを作れます。

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

function ProtectedRoute({ children }) {
  const isLoggedIn = checkAuthStatus(); // ログイン状態を確認

  if (!isLoggedIn) {
    // 未ログインならログインページへ
    return <Navigate to="/login" />;
  }

  return children;
}

// 使用例
const router = createBrowserRouter([
  {
    path: "/dashboard",
    element: (
      <ProtectedRoute>
        <Dashboard />
      </ProtectedRoute>
    ),
  },
]);

これは、会員制のジムやクラブのようなものです。 会員証(ログイン状態)がないと、受付(ログインページ)に案内されます。

よくある質問

Q: ページ遷移時にスクロール位置がそのままになってしまう

A: React Routerではページ遷移後も前のスクロール位置を保持します。 ページトップに戻したい場合は、以下のコンポーネントを追加してください。

import { useEffect } from "react";
import { useLocation } from "react-router-dom";

function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}

Q: ブラウザの戻るボタンが効かない

A: Linkコンポーネントではなく、通常の<a>タグやwindow.locationを使っていませんか? React RouterのLinkuseNavigateを使うことで、履歴管理が正しく動作します。

Q: 404ページを表示したい

A: ルート設定の最後に、すべてのパスにマッチする設定を追加します。

const router = createBrowserRouter([
  // 他のルート設定...
  {
    path: "*",
    element: <NotFoundPage />,
  },
]);

まとめ

React Router v7を使うと、URLベースの画面遷移が簡単に実装できます。

基本的な考え方は「URLと画面の対応表を作る」こと。 まるで、建物の階数と部屋の対応表のようなものです。

最初は単純なルート設定から始めて、徐々に以下の機能を追加していくのがおすすめです。

  • ネストされたルートで共通レイアウトを作る
  • 動的パラメータで柔軟な画面を実現する
  • 認証が必要なページを保護する

React Routerは、SPAでありながら従来のWebサイトのような使い心地を実現します。 ユーザーにとって自然な操作感を提供できるのが大きな魅力です。

ぜひ実際に手を動かして、URLと画面の関係を体感してみてください。

共有:

著者について

とまだ

とまだ

フルスタックエンジニア

Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。

著者の詳細を見る →