3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【v8対応】React Routerの書き方を忘れていたのでまとめる

3
Last updated at Posted at 2026-09-17

はじめに

React Routerの使い方や書き方を結構忘れていたのでまとめます。
調べていても、v6以前の書き方だったりして、最新の書き方が分かりにくかったので、最新の書き方をまとめます。
バージョン6以前とは書き方が大きく変わりますのでご注意ください。

動作環境

  • React 19.2.8
  • vite 8.3.0
  • React Router 8.4.0

react-routerとreact-router-domの違い

本題に入る前の豆知識です。
Reactでルーティングを実装する時に利用するReact Routerですが、react-routerとreact-router-domが2種類あります。

  • react-router:React Routerのコア機能
  • react-router-dom:React Routerにブラウザ向けの機能を追加したパッケージ

react-router-domには<BrowserRouter>や<Link>などブラウザで使う機能が導入されていたため、Web開発では基本的にreact-router-domを使用するのが一般的でした。
React Router v7からreact-routerとreact-router-domの統合・統一がされてreact-routerからもreact-router-domの機能を使えるようになりました。
そのため、react-routerをインストールしてもreact-router-domの機能を利用できます。(v7以前のReact Routerではエラーになるので注意)

npm install react-router

当記事ではreact-routerを使用し、執筆時点の最新バージョンである8.4.0を利用しています。

基本設定

ルーティング設定をアプリ全体に適用する

アプリのエントリーポイントとなるコンポーネントに次のように書きます。

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>,
)

<BrowserRouter>で囲うことでルーティングの設定が有効化されます。

ルート設定をする

URLに割り当てるコンポーネントを設定します。

import { Routes, Route } from 'react-router';
import Home from './Home';
import Page1 from './Page1';
import Page2 from './Page2';

const App = () => {
  return (
    <Routes>
      <Route index element={<Home />} />
      <Route path='/page1' element={<Page1 />} />
      <Route path='/page2' element={<Page2 />} />
    </Routes>
  );
}

export default App;

Routeに次のようにURLとコンポーネントを指定してURLとコンポーネントを紐づけます。

<Route path='URL' element={{/* コンポーネント */}} />

pathにURLを指定し、elementに表示するコンポーネントを指定します。pathではなくindexを指定するとトップページとして扱われます。
RouteはRoutesで囲まないと有効にならないので注意です。

画面遷移

ページ遷移をするためのリンクを設置します。

import { Link } from "react-router";

const Home = () => {
    return (
        <>
            <h1>トップページです</h1>
            <Link to="/page1">ページ1</Link>
            <Link to="/page2">ページ2</Link>
        </>
    );
}

export default Home;

<Link>のtoにURLを指定することでリンクを設置できます。
<Link to='URL'>...</Link>
<Link>は<a>タグの代わりに使います。<a>タグを使うとページがリロードされてしまうので注意です。

ただ、<Link>は内部的にはaタグを使っているようなので、ブラウザの検証ツールから確認すると<a>タグとして表示されます。
そのため、target="_blank"などのaタグの属性を指定することも可能です。

<Link to='URL' target="blank">...</Link>

リンクを用いない画面遷移

リンククリック以外で画面遷移を行いたい場合はuseNavigateを使います。

import { useNavigate } from "react-router";

const Page1 = () => {
    const navigate = useNavigate();
    const onClickBack = () => navigate(-1);
    return (
        <>
            <h1>Page1です</h1>
            <button onClick={onClickBack}>前のページへ戻る</button>
        </>
    );
}

export default Page1;

useNavigateはReact Routerのフックで、画面遷移を行うための処理を行います。
navigateの引数にURLを指定することで画面遷移が可能です。数字を指定すると履歴の前後に遷移することもできます。

ログイン後やフォーム送信後に画面遷移を行う場合などに利用できます。

import { useNavigate } from 'react-router'

const LoginForm = () => {
  const navigate = useNavigate();
  const handleSubmit = () => {
    // ログイン処理
    navigate('/dashboard') // ログイン後にダッシュボードへ
  }

  return <button onClick={handleSubmit}>ログイン</button>
}

ネストされたページの画面遷移

次のようなネストされたページを設置する場合は、2パターンの書き方があります。

/page1
└── detailA

ネストされたページを設置するパターン1

import { Routes, Route } from 'react-router';
import Page1 from './Page1';
import Page1DetailA from './Page1DetailA';

const App = () => {
  return (
    <Routes>
      <Route path='/page1' element={<Page1 />} />
      <Route path='/page1/detailA' element={<Page1DetailA />} />
    </Routes>
  );
}

export default App;

<Route>のpathにネストされたURLを指定することでネストされたページを設置できます。
並列に<Route>を設置していくのでシンプルで分かりやすいですね。

こちらの書き方は、ネストされたページが少ない場合や、ネストの階層が浅い場合に向いています。
また後述する<Outlet>を使用せず、単純にURLごとに独立した画面を割り当てる場合に便利です。

ネストされたページを設置するパターン2

import { Routes, Route } from 'react-router';
import Page1 from './Page1';
import Page1DetailA from './Page1DetailA';

const App = () => {
  return (
    <Routes>
      <Route path='/page1'>
        <Route index element={<Page1 />} />
          <Route path='detailA' element={<Page1DetailA />}>
        </Route>
      </Route>
    </Routes>
  );
}

export default App;

<Route path='/page1'>の中に<Route path='detailA'>を設置することで、URLの/page1を省略して書くことができます。
<Route index element={<Page1 />} />は/page1のトップページとして扱われます。その中に<Route path='detailA'>を設置することで、/page1/detailAのURLにアクセスした場合にPage1DetailAが表示されます。

さらに階層を深くする場合は次のように書きます。

import { Routes, Route } from 'react-router';
import Page1 from './Page1';
import Page1DetailA from './Page1DetailA';
import Page1DetailAItem01 from './Page1DetailAItem01'; // 追加

const App = () => {
  return (
    <Routes>
      <Route path='/page1'>
        <Route index element={<Page1 />} />
        {/* 第2階層 */}
          <Route path='detailA'>
            <Route index element={<Page1DetailA />} />
            {/* 第3階層 */}
              <Route path='item01'>
                <Route index element={<Page1DetailAItem01 />} />
              </Route>
            </Route>
          </Route>
    </Routes>
  );
}

export default App;

こちらの書き方は、ネストされたページが多い場合や、ネストの階層が深い場合に向いています。
また次の<Outlet>を使用することで、共通レイアウトを設置できます。

import { Routes, Route } from 'react-router';
import Page1 from './Page1';
import Page1DetailA from './Page1DetailA';
import Page1Layout from './Page1Layout'; // 追加

const App = () => {
  return (
    <Routes>
      <Route path='/page1' element={<Page1Layout />}>
        <Route index element={<Page1 />} />
          <Route path='detailA' element={<Page1DetailA />}>
        </Route>
      </Route>
    </Routes>
  );
}

export default App;

<Outlet>はReact Router v6から導入されたコンポーネントで、親コンポーネントの中に子コンポーネントを表示するための場所を指定できます。
<Route path='/page1' element={<Page1Layout />}>の中に書いた子コンポーネントは次の<Outlet />の位置に表示されます。

import { Outlet } from "react-router";

const Page1Layout = () => {
  return (
    <>
      <header>Page1共通ヘッダー</header>
      <main>
        <Outlet /> // ここに子コンポーネントが表示される
      </main>
      <footer>Page1共通フッター</footer>
    </>
  );
};

export default Page1Layout;

<Outlet>を使用しない場合は親のルートにelementを省略した<Route path='/page1'>と書いてURLのグループ化として使用し、
<Outlet>を使用する場合は親のルートにelementを指定して親コンポーネントを共通レイアウトとして使用します。

URLパラメータの利用

商品ページやユーザーページなど、URLにIDを含めてページを表示する場合はURLパラメータを利用します。

import { Routes, Route } from 'react-router';
import UserProfile from './UserProfile';

const App = () => {
  return (
    <Routes>
          <Route path='/profile/:id' element={<UserProfile />} />
    </Routes>
  );
}

export default App;

/profile/:idのように:をつけることでURLパラメータを指定できます。:以降の文字列はid以外も指定できます。/profile/1のようにアクセスすると、idの値が1として取得できます。

import { useParams } from "react-router";

const UserProfile = () => {
    const { id } = useParams();
    return <p>ようこそ!ユーザーID:{id}</p>
}

export default UserProfile;

URLパラメータを取得したい場合はuseParamsを使用します。useParamsはReact Routerのフックで、URLパラメータを取得するための処理を行います。

クエリパラメータの利用

サイト内検索などでURLのクエリパラメータを取得する場合はuseSearchParamsを使用します。

import { useSearchParams } from "react-router";

const Search = () => {
    const [searchParams, setSearchParams] = useSearchParams();
    return <p>検索キーワード:{searchParams.get("text")}</p>; // ?text=〇〇のURLクエリパラメータを取得できる
}

export default Search;

useSearchParamsはReact Routerのフックで、URLのクエリパラメータを取得するための処理を行います。別のフックであるuseLocationを使用してもクエリパラメータを取得できますが、useSearchParamsの方が簡単に取得でき、setSearchParamsを使用することでクエリパラメータの書き換えも可能です。

import { useSearchParams } from "react-router";

const Search = () => {
    const [searchParams, setSearchParams] = useSearchParams();
    const handleFilterChange = () => setSearchParams({ text: "hoge" });
    return (
        <>
            <p>検索キーワード:{searchParams.get("text")}</p>
            <button onClick={handleFilterChange}>条件変更</button>
        </>
    );
}

export default Search;

遷移先のページにデータを受け渡す

URLにパラメータを含めずに、遷移先のページにデータを受け渡す場合は<Link>のstateを使用します。

// stateにオブジェクトを指定するパターン
<Link to="/profile" state={{id: 1, name: "hoge"}}>プロフィール</Link>

<Link>のstateにオブジェクトを指定することで、遷移先のページにデータを受け渡すことができます。

<Link>のstateに指定したオブジェクトは、遷移先のページでuseLocationを使用することで取得できます。

import { useLocation } from "react-router";

const UserProfile = () => {
    const location = useLocation();
    const { id, name } = location.state || {};
    return (
        <>
            <p>ユーザーID:{id}</p>
            <p>ユーザーネーム:{name}</p>
        </>
    );
}

export default UserProfile;

注意点として、<Link>のstateに指定したオブジェクトは、ページのリロードやURLの直接入力で消えてしまいます。そのため、次のようにデータが存在しない場合の処理の追加をしておきましょう。

import { Link, useLocation } from "react-router";

const UserProfile = () => {
    const location = useLocation();
    const { id, name } = location.state || {};
    // location.stateが存在しない場合の処理
    if (!location.state) {
        return (
            <>
                <p>データが取得できませんでした。</p>
                <Link to="/">トップページへ戻る</Link>
            </>
        );
    }
    return (
        <>
            <p>ユーザーID:{id}</p>
            <p>ユーザーネーム:{name}</p>
        </>
    );
}

export default UserProfile;

404ページを設置する

存在しないURLにアクセスした場合に表示する404ページを設置します。

import { Routes, Route } from 'react-router';
import NotFound from './NotFound';

const App = () => {
  return (
    <Routes>
        <Route path='*' element={<NotFound />} />
    </Routes>
  );
}

export default App;

<Route path='*' element={<NotFound />} />のようにpathに*を指定することで、存在しないURLにアクセスした場合に表示する404ページを設置できます。

404ページのコンポーネントは次のような感じで良いと思います。

import { Link } from "react-router";

const NotFound = () => {
    return (
            <>
                <p>ページが見つかりません。</p>
                <Link to="/">トップページへ戻る</Link>
            </>
        );
}

export default NotFound;

なお404ページを設置する場合は、<Route path='*' element={<NotFound />} />は最後に書くようにしましょう。React Routerは上から順にルートを評価していくため、<Route path='*' element={<NotFound />} />が先に書かれていると、すべてのURLが404ページとして扱われてしまいます。

最後に

React Routerでよく使う機能をまとめました。React Router v6から書き方が大きく変わったので、調べる際のバージョンの確認は必ず行いましょう。

自分の体感ですがけっこうv6以前の書き方の情報が多いので、ドキュメントを確認するのが一番確実です。

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?