はい、承知いたしました。React Router DOMの最も基本的な紹介から使い方、そして実践的な例までを詳細に解説する、約5000語の記事を記述します。
いちばんやさしいReact Router DOM紹介と使い方:クライアントサイドルーティングの基本を徹底解説
はじめに:なぜReactアプリケーションにルーティングが必要なのか?
WebサイトやWebアプリケーションにおいて、「ルーティング」とは、ユーザーがアクセスしたURLに応じて、どのページ(またはコンポーネント)を表示するかを決定し、切り替える仕組みのことです。例えば、https://example.com/about にアクセスしたら会社概要ページが表示され、https://example.com/products にアクセスしたら商品一覧ページが表示される、といった挙動はルーティングによって実現されています。
従来のWebサイトでは、ユーザーが別のページへのリンクをクリックするたびに、ブラウザはサーバーに新しいページのHTMLファイルを要求し、受け取ったHTMLをレンダリングし直す、というプロセスを繰り返していました。これは「サーバーサイドルーティング」または「ページ遷移」と呼ばれるものです。
しかし、ReactのようなモダンなJavaScriptフレームワーク/ライブラリを使って開発されるアプリケーションの多くは、「Single Page Application (SPA)」と呼ばれるアーキテクチャを採用しています。SPAでは、最初に一度だけHTMLファイルと必要なJavaScript・CSSファイルを読み込んだ後、その後の画面の切り替えはJavaScriptが動的にDOM(Document Object Model)を操作して行います。ページ全体の再読み込みが発生しないため、ネイティブアプリケーションのようなスムーズで高速なユーザー体験を提供できるのが大きなメリットです。
SPAの利点は多い一方で、課題も存在します。それは、ブラウザのネイティブなページ遷移(URL変更とそれに伴うページ全体の再読み込み)を利用しないため、URLと表示されるコンテンツを同期させる仕組みを自分たちで作る必要がある、という点です。ユーザーがブラウザのアドレスバーに直接URLを入力してアクセスした場合、あるいは「戻る」「進む」ボタンをクリックした場合に、アプリケーションは現在のURLを正しく解釈し、対応する画面を表示しなければなりません。また、特定の画面へのリンクを他のユーザーと共有できるように、URLを意味のあるものにする(パーマリンク)必要もあります。
このSPAにおける「クライアントサイドルーティング」(ブラウザ側、つまりJavaScriptがURLに基づいて画面表示を切り替えること)を実現するための、Reactにおけるデファクトスタンダード(事実上の標準)ライブラリが、React Router DOM です。
この記事では、React Router DOMの最も基本的な使い方から、主要なコンポーネントの詳細、そして実践的な例までを、初心者の方でも理解できるように、コードを交えながら丁寧に解説していきます。この記事を最後まで読めば、React Router DOMを使って簡単なナビゲーションを持つSPAを構築できるようになるはずです。
対象読者:
- Reactの基本的な書き方は知っているが、ルーティングについては初めて学ぶ方
- React Router DOMの使い方をゼロから学びたい方
- Reactアプリケーションに複数のページや画面を作成したい方
この記事で学ぶこと:
- Reactアプリケーションにおけるルーティングの必要性
- React Router DOMとは何か
- React Router DOMのインストール方法
BrowserRouter,Routes,Route,Linkといった主要なコンポーネントの使い方- URLパラメーターやクエリパラメーターの利用方法 (
useParams,useSearchParams) - プログラムによる画面遷移 (
useNavigate) - ネストされたルート (Nested Routes) の基本的な考え方
- 404ページの実装方法
- NavLinkを使ったアクティブリンクのスタイリング
- よくある疑問とトラブルシューティング
さあ、React Router DOMの世界へ足を踏み入れましょう!
Reactアプリケーションにおけるルーティングの課題(もう少し詳しく)
SPAの最大の利点は、スムーズな画面遷移です。リンクをクリックしてもページ全体がリロードされないため、ユーザーはストレスなくアプリケーション内を移動できます。まるでネイティブアプリを使っているかのような体験です。
しかし、このスムーズさは、ブラウザが持つ本来の「ページ遷移」の仕組みを使わないことで実現されています。従来のウェブサイトでは、リンクをクリックするとブラウザが新しいHTMLファイルをサーバーに要求し、その新しいHTMLで画面全体を置き換えます。ブラウザのアドレスバーのURLも、要求したファイルのパスに合わせて変化します。
SPAでは、このHTMLファイルの要求・再読み込みを行いません。最初のページ読み込み時に、アプリケーションに必要なすべての(または多くの)JavaScriptコードがブラウザにダウンロードされます。その後の画面の切り替えは、ダウンロードされたJavaScriptコードが実行され、DOMの一部を書き換えることで行われます。
ここで問題になるのが、URLと表示されている画面の状態をどうやって同期させるか、です。
- URLのアドレスバーの表示: 画面が切り替わっても、アドレスバーのURLが変わらなければ、ユーザーは現在どの画面を見ているのか分かりません。また、そのURLをブックマークしたり、他の人に共有したりすることができません。
- ブラウザの「戻る」「進む」ボタン: ブラウザの「戻る」ボタンをクリックしたときに、アプリケーションは一つ前の画面状態に戻る必要があります。「進む」ボタンも同様です。ページ全体の再読み込みを伴わないSPAでは、この履歴管理を自分たちで行う必要があります。
- 直接アクセス: ユーザーがブラウザのアドレスバーに直接
/products/123のようなURLを入力してエンターキーを押した場合、アプリケーションはURLの情報を読み取って、対応する商品ID 123の詳細画面を正しく表示する必要があります。
これらの課題を解決し、SPAでも従来のWebサイトと同じようにURLベースのナビゲーションを可能にするのが、クライアントサイドルーティングライブラリの役割です。React Router DOMは、Reactアプリケーションでこのクライアントサイドルーティングを実現するための、最も一般的で強力なライブラリです。
React Router DOMとは何か?
React Router DOMは、Reactアプリケーションに宣言的なクライアントサイドルーティングを提供する標準的なライブラリです。
「宣言的ルーティング」とは、どのようなパスに対してどのコンポーネントを表示したいかを、「〜ならば〜を表示する」という具体的な手順ではなく、「パス/about が来たら About コンポーネントを表示する」のように、目的や状態を宣言的に記述することで実現する考え方です。Reactのコンポーネント指向と非常に相性が良いです。React Router DOMは、ルーティングに関する設定を特別なファイルに記述するのではなく、Reactコンポーネントとして記述します。
react-router と react-router-dom の違い
React Routerは、ルーティングのコア機能を提供するライブラリです。これは、Webだけでなく、React Nativeなどの他のプラットフォームでも使用できる、プラットフォーム非依存の機能を含んでいます。
一方、React Router DOM は、react-router のコア機能に加えて、Webブラウザ(DOM環境)でのルーティングに必要な機能(ブラウザの履歴APIとの連携、URLに基づいたナビゲーションなど)を追加したものです。Reactを使った通常のWebアプリケーション開発では、react-router-dom をインストールして使用します。この記事でも react-router-dom を扱います。
React Router DOMは、ブラウザの履歴API (pushState, replaceState など) を利用して、ページを再読み込みすることなくURLを変更し、履歴を管理します。そして、現在のURLに基づいて、どのReactコンポーネントをレンダリングすべきかを判断し、表示を切り替えます。
環境構築とインストール
React Router DOMを使うには、まずReactアプリケーションが必要です。まだReactアプリケーションを作成していない場合は、ViteまたはCreate React App (CRA) を使って新しいプロジェクトを作成しましょう。現在はViteを使うのが一般的で推奨されています。
Viteを使ったプロジェクト作成(推奨):
bash
npm create vite@latest my-react-app --template react
または
bash
yarn create vite my-react-app --template react
または
bash
pnpm create vite my-react-app --template react
プロジェクトフォルダ(my-react-app)に移動し、依存関係をインストールします。
bash
cd my-react-app
npm install
または
bash
cd my-react-app
yarn install
または
bash
cd my-react-app
pnpm install
Create React Appを使ったプロジェクト作成(非推奨ですが、古いプロジェクトなどで使うこともあります):
bash
npx create-react-app my-react-app
または
bash
yarn create react-app my-react-app
プロジェクトフォルダ(my-react-app)に移動します。
bash
cd my-react-app
React Router DOMのインストール
Reactプロジェクトの準備ができたら、次に react-router-dom をインストールします。プロジェクトフォルダのルートで以下のコマンドを実行してください。
bash
npm install react-router-dom
または
bash
yarn add react-router-dom
または
bash
pnpm add react-router-dom
これで、あなたのReactプロジェクトでReact Router DOMを使う準備が整いました。
基本的な使い方:最小構成を知る
React Router DOMを使ったクライアントサイドルーティングは、いくつかの主要なコンポーネントを組み合わせて実現されます。まずは最も基本的な構成を見ていきましょう。
必要な主要コンポーネント:
BrowserRouter: アプリケーション全体をラップし、ブラウザの履歴APIを使ってURLとUIを同期させます。React Router DOMを使うアプリケーションのルート(最上位)に配置する必要があります。Routes: 複数のRouteコンポーネントを囲むコンテナです。現在のURLにマッチする最初のRouteを探し、その要素をレンダリングします。v6から導入されたコンポーネントで、以前のバージョンのSwitchに相当しますが、より柔軟で効率的になっています。Route: 特定のURLパスと、そのパスがマッチしたときに表示するコンポーネント(または要素)を紐付けます。pathプロパティでマッチさせるURLを指定し、elementプロパティでレンダリングするReact要素を指定します。Link: クリックすると別のURLへナビゲートするためのコンポーネントです。ブラウザのページ遷移を使わずに、React Router DOMが内部でURLを変更し、対応するコンポーネントをレンダリングさせます。これはHTMLの<a>タグに似ていますが、SPA内でのスムーズな遷移のために使われます。
では、これらのコンポーネントを使った簡単な例を見てみましょう。
まず、表示するいくつかのシンプルなコンポーネントを作成します。例えば、Home.js, About.js, Contact.js の3つです。
“`javascript
// src/components/Home.js
import React from ‘react’;
function Home() {
return (
ホーム
ここはホーム画面です。
);
}
export default Home;
“`
“`javascript
// src/components/About.js
import React from ‘react’;
function About() {
return (
会社概要
このアプリケーションについての情報です。
);
}
export default About;
“`
“`javascript
// src/components/Contact.js
import React from ‘react’;
function Contact() {
return (
お問い合わせ
お問い合わせはこちらへ。
);
}
export default Contact;
“`
次に、これらのコンポーネントをルーティングで切り替えるように設定します。通常は、アプリケーションのルートコンポーネント(例: src/App.js)や、ルーティングを設定したい特定の場所に記述します。
src/App.js を以下のように変更します。
“`javascript
// src/App.js
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
import Home from ‘./components/Home’;
import About from ‘./components/About’;
import Contact from ‘./components/Contact’;
function App() {
return (
// BrowserRouterでアプリケーション全体をラップする
<hr /> {/* 見た目の区切り線 */}
{/* Routesコンポーネントの中でRouteを定義する */}
{/* 現在のURLにマッチする最初のRouteがレンダリングされる */}
<Routes>
{/* path="/" にマッチしたら Home コンポーネントをレンダリング */}
<Route path="/" element={<Home />} />
{/* path="/about" にマッチしたら About コンポーネントをレンダリング */}
<Route path="/about" element={<About />} />
{/* path="/contact" にマッチしたら Contact コンポーネントをレンダリング */}
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
このコードを説明します。
- まず、
react-router-domから必要なコンポーネント (BrowserRouter,Routes,Route,Link) をインポートしています。 - 作成した各ページコンポーネント (
Home,About,Contact) もインポートします。 - アプリケーションのルートコンポーネントである
Appの中で、返すJSX全体を<BrowserRouter>で囲んでいます。これはReact Router DOMを使う上での必須設定です。 <nav>要素の中に、各ページへのナビゲーションリンクをリストとして作成しています。ここでHTML標準の<a href="...">タグではなく、react-router-domからインポートした<Link to="...">コンポーネントを使っているのがポイントです。Linkは、クリックしてもページ全体を再読み込みせず、SPA内でスムーズな画面遷移を実現します。toプロパティに行き先のパスを指定します。- 次に
<Routes>コンポーネントを配置しています。このRoutesの中に、アプリケーションで扱うそれぞれのルート(パスとコンポーネントの対応関係)を定義します。 - それぞれのルートは
<Route>コンポーネントとして定義します。path="/" element={<Home />}は、「URLパスが/(サイトのルート)にマッチしたら、<Home />コンポーネントをレンダリングしてください」という意味です。path="/about" element={<About />}は、「URLパスが/aboutにマッチしたら、<About />コンポーネントをレンダリングしてください」という意味です。path="/contact" element={<Contact />}は、「URLパスが/contactにマッチしたら、<Contact />コンポーネントをレンダリングしてください」という意味です。elementプロパティには、パスがマッチしたときに実際にレンダリングしたいReact要素(通常はコンポーネント)を指定します。
この設定でアプリケーションを実行すると、画面上部に「ホーム」「会社概要」「お問い合わせ」というリンクが表示されます。これらのリンクをクリックすると、URLが /、/about、/contact と変化し、それに応じて Routes の中に定義された Route が現在のURLにマッチするかを判定し、マッチした Route の element に指定されたコンポーネント (Home, About, Contact) が <Routes> の場所に表示されます。
これがReact Router DOMの最も基本的な使い方です。ブラウザのアドレスバーのURLと、表示されるコンテンツが連携して動くようになります。
主要コンポーネントの詳細解説
ここからは、先ほど登場した主要なコンポーネントについて、さらに詳しく見ていきましょう。
BrowserRouter
- 役割: アプリケーションのルートに配置し、ブラウザの履歴API (
history.pushState,history.replaceState) を使用してURLを管理し、React Router DOMがURLの変更を検知できるようにします。 - なぜ必要か: React Router DOMがブラウザのURL変更イベントを購読したり、プログラムでURLを変更したりするためには、この
BrowserRouterのコンテキストが必要です。SPAでページ全体の再読み込みなしにURLを操作するために、ブラウザの履歴APIを使いますが、BrowserRouterはそのAPIを抽象化し、React Router DOMの内部で使いやすくしてくれています。 -
使い方:
“`javascript
import { BrowserRouter } from ‘react-router-dom’;
import App from ‘./App’; // あなたのアプリケーションのルートコンポーネント// 通常は src/index.js (または src/main.jsx for Vite) でアプリケーション全体をラップします
const container = document.getElementById(‘root’);
const root = createRoot(container); // ReactDOMのcreateRootを使用 (React 18+)root.render(
{/ ここでBrowserRouterを使ってアプリケーション全体を囲む /}
);
``src/index.js
多くの場合、アプリケーションのエントリーポイントファイル(例:やsrc/main.jsx)で、ReactDOMのrenderまたはcreateRoot().renderメソッドを使って、アプリケーションのルートコンポーネント(通常は)をレンダリングする際に、その外側を` でラップします。
Routes
- 役割: 複数の
<Route>コンポーネントをグループ化するためのコンテナです。現在のURLと、子として含まれる各<Route>のpathを比較し、最初にマッチしたRouteの要素(elementに指定したもの)をレンダリングします。 - なぜ必要か:
Routesが存在することで、React Router DOMは複数のルート定義の中から、現在のURLに最適なルートを効率的に見つけ出すことができます。v6では、Routesの中で定義された<Route>は、最も具体的な(より長く正確な)パスから順にマッチングを試みるようになり、以前のバージョンのexactプロパティが不要になりました。また、子ルートや相対パスの扱いもRoutesを中心に行われます。 -
使い方:
“`javascript
import { Routes, Route } from ‘react-router-dom’;
// 各ページコンポーネントをインポートfunction App() {
return (
{/ … ナビゲーションなど … /}
{/ RouteコンポーネントをRoutesの中に配置 /}
} />
} />
{/ … 他のRoute … /}
{/ … フッターなど … /}
);
}
``Routesの中に直接コンポーネントを子として配置します。Routesは現在のURLにマッチする **最初の** 子Routeだけをレンダリングします(親ルートがマッチした場合は、その中のOutlet` に子ルートがレンダリングされます。これはネストされたルートのセクションで詳しく説明します)。
Route
- 役割: 特定のURLパスと、表示するReact要素(通常はコンポーネント)を関連付けます。
- 主なプロパティ:
path: マッチさせたいURLパスを指定します。静的なパス(例:/about)だけでなく、動的なパスセグメント(例:/products/:productId)やワイルドカード(例:*)も指定できます。element:pathが現在のURLにマッチしたときにレンダリングされるReact要素を指定します。<ComponentName />の形式で記述するのが一般的です。v6から導入されたプロパティで、以前のバージョンのcomponentやrenderの代わりに使われます。
-
使い方:
“`javascript
import { Routes, Route } from ‘react-router-dom’;
import Home from ‘./components/Home’;
import About from ‘./components/About’;
{/ パスが “/” にマッチしたらを表示 /}
} /> {/ パスが “/about” にマッチしたら
を表示 /}
} /> {/ 動的なパスセグメントを含むルート /}
} /> {/ マッチするルートがない場合のフォールバック (404ページなど) /}
} />
``Routeコンポーネントは必ずRoutes` コンポーネントの子として配置する必要があります。 -
exactプロパティについて (v6では不要に): 以前のバージョンのReact Routerでは、path="/" element={<Home />}のようなルート定義で、/だけでなく/aboutや/contactといった/で始まるすべてのパスにHomeコンポーネントがマッチしてしまう問題を避けるために、exactプロパティ (<Route exact path="/" ...>) を使用する必要がありました。しかし、React Router v6のRoutesコンポーネントは、自動的に最適な(最も具体的な)ルートを優先的にマッチさせるように設計されているため、基本的にexactプロパティは不要になりました。path="/"はルートパスのみにマッチし、/aboutなどにはマッチしません。
Link
- 役割: SPA内で別のURLへ遷移するためのナビゲーション要素を作成します。HTMLの
<a>タグのように見えますが、クリックしてもブラウザのページ全体の再読み込みを行わず、React Router DOMが内部的にURLを変更し、対応するルートのコンポーネントをレンダリングさせます。 - 主なプロパティ:
to: 遷移先のURLパスを指定します。文字列またはオブジェクトで指定できます。
-
使い方:
“`javascript
import { Link } from ‘react-router-dom’;``
* **タグとの違い:** HTMLのタグは、クリックするとブラウザに新しいページを要求させ、ページ全体が再読み込みされます。SPAではこれを避けるため、Linkコンポーネントを使用します。Linkは内部的には` タグをレンダリングしますが、クリックイベントを横取りしてデフォルトのブラウザの挙動(ページ再読み込み)を阻止し、React Router DOMの履歴APIを使ってURLを変更します。これにより、画面の一部だけが更新されるスムーズな遷移が実現されます。
実践的な例:簡単なナビゲーションバーの作成
先の基本的な使い方で見た App.js のコードは、簡単なナビゲーションバーと、それに連動して表示が切り替わるコンテンツエリアの例として非常によくできています。
“`javascript
// src/App.js (再掲)
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
import Home from ‘./components/Home’;
import About from ‘./components/About’;
import Contact from ‘./components/Contact’;
function App() {
return (
<hr />
{/* URLに応じたコンテンツ表示エリア */}
<Routes> {/* Route定義のコンテナ */}
<Route path="/" element={<Home />} /> {/* "/" にマッチしたら <Home /> を表示 */}
<Route path="/about" element={<About />} /> {/* "/about" にマッチしたら <About /> を表示 */}
<Route path="/contact" element={<Contact />} /> {/* "/contact" にマッチしたら <Contact /> を表示 */}
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
この構造は、多くのSPAの基本的なレイアウトパターンです。上部に常に表示されるナビゲーション(ヘッダーの一部として)、そしてその下にURLに応じて内容が切り替わるメインコンテンツエリアがあります。
<nav> の中に置かれた <Link> は、ユーザーがクリックするためのUI要素です。ユーザーが例えば「会社概要」リンクをクリックすると、ブラウザのアドレスバーのURLは /about に変わりますが、ページ全体はリロードされません。
その下にある <Routes> コンポーネントは、その時点でブラウザのアドレスバーに表示されているURL(この例では /about)を見て、自身の子である <Route> の path と比較します。path="/about" の <Route> がマッチすると判断し、その element に指定されている <About /> コンポーネントがレンダリングされ、<Routes> コンポーネントがあった場所に表示されます。
このように、React Router DOMは、<Link> によるURL変更をトリガーとして、<Routes> が現在のURLに基づいて適切な <Route> を探し、その element をレンダリングするという流れで、画面の切り替えを実現します。
URLパラメーターの利用 (useParams)
アプリケーションを開発していると、特定のアイテム(例: 商品、ユーザー、記事など)の詳細ページを表示したいことがよくあります。これらの詳細ページは、表示するアイテムによって内容が異なりますが、ページのデザインやレイアウトは共通していることが多いです。
例えば、商品詳細ページを表示する場合、URLを /products/1 や /products/2 のように、アイテムのIDを含めるのが一般的です。この 1 や 2 の部分は動的に変化します。React Router DOMでは、このような動的な部分を「URLパラメーター」として扱うことができます。
URLパラメーターを定義するには、<Route path> の中に :パラメーター名 の形式で記述します。例えば、商品IDをパラメーターとして受け取る場合は path="/products/:productId" のように定義します。
このパラメーターの値を、マッチしたルートでレンダリングされるコンポーネント内で取得するには、useParams フックを使用します。useParams は、URLに含まれるすべてのパラメーターをキーと値のペアとして持つオブジェクトを返します。
例を見てみましょう。商品詳細ページを表示するコンポーネント ProductDetail.js を作成し、URLパラメーターから商品IDを取得して表示してみます。
まず、ProductDetail.js コンポーネントを作成します。
“`javascript
// src/components/ProductDetail.js
import React from ‘react’;
import { useParams } from ‘react-router-dom’; // useParamsフックをインポート
function ProductDetail() {
// useParamsフックを使って、URLパラメーターを取得
// Routeのpathで定義した “:productId” というキーで値を取得できる
const { productId } = useParams();
// 実際にはここで取得したproductIdを使って、APIから商品データをフェッチするなどの処理を行う
return (
商品詳細
{/ 取得したproductIdを表示 /}
商品のID: {productId}
{/
ここに商品名や説明、画像などの詳細情報が表示されます。
/}
);
}
export default ProductDetail;
“`
次に、App.js の <Routes> の中に、この ProductDetail コンポーネントに対応するルート定義を追加します。
“`javascript
// src/App.js (一部変更)
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
import Home from ‘./components/Home’;
import About from ‘./components/About’;
import Contact from ‘./components/Contact’;
import ProductDetail from ‘./components/ProductDetail’; // ProductDetailをインポート
function App() {
return (
<hr />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
{/* 動的なパスセグメント ":productId" を含むルート */}
{/* 例: /products/123 や /products/abc にマッチする */}
<Route path="/products/:productId" element={<ProductDetail />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
これで、/products/123 や /products/456 といったURLにアクセスすると、ProductDetail コンポーネントがレンダリングされ、その中で useParams フックを使って :productId の部分の値 ("123" や "456") を取得できるようになります。
useParams フックの注意点:
useParamsは、コンポーネントが<Routes>の中の<Route>によって直接、またはネストされたルートの<Outlet>を通じてレンダリングされた場合にのみ機能します。BrowserRouterの直接の子など、ルート定義と関連付けられていない場所では使用できません。- 返されるパラメーターの値は常に文字列です。数値として扱いたい場合は、
parseInt()などで変換する必要があります。
クエリパラメーターの利用 (useSearchParams)
URLには、パスの他に「クエリパラメーター」という形で追加の情報を含めることがあります。クエリパラメーターは、URLの ? の後に キー=値 の形式で記述され、複数の場合は & で連結されます。例えば /products?category=electronics&sort=price のような形式です。これらは主に、リストのフィルタリング、ソーティング、ページネーションなどの状態を保持するために使われます。
React Router DOM v6では、クエリパラメーターを扱うために useSearchParams フックが提供されています。useSearchParams フックは、URLのクエリ文字列を読み取ったり、更新したりするための機能を提供します。
useSearchParams フックは、要素が2つの配列を返します。
- 現在のクエリパラメーターを表現する
URLSearchParamsオブジェクト。 - クエリパラメーターを更新するための関数。
例として、商品リストをカテゴリでフィルタリングする機能を考えてみましょう。
“`javascript
// src/components/ProductList.js
import React from ‘react’;
import { Link, useSearchParams } from ‘react-router-dom’; // useSearchParamsをインポート
function ProductList() {
// useSearchParamsフックを使って、[クエリパラメーターオブジェクト, 更新関数]を取得
const [searchParams, setSearchParams] = useSearchParams();
// 現在のカテゴリを取得 (URLが ?category=xxx なら ‘xxx’、なければ null)
const category = searchParams.get(‘category’);
// 表示する商品データのダミー(実際はAPIから取得)
const products = [
{ id: 1, name: ‘ノートパソコン’, category: ‘electronics’ },
{ id: 2, name: ‘本’, category: ‘books’ },
{ id: 3, name: ‘スマートフォン’, category: ‘electronics’ },
{ id: 4, name: ‘雑誌’, category: ‘books’ },
];
// 現在のカテゴリでフィルタリング
const filteredProducts = category
? products.filter(p => p.category === category)
: products; // categoryがなければ全て表示
// クエリパラメーターを更新する関数(例えば、フィルタボタンのクリックハンドラなど)
const handleFilterChange = (newCategory) => {
if (newCategory) {
// クエリパラメーターに category=newCategory を設定
setSearchParams({ category: newCategory });
} else {
// クエリパラメーターをクリア
setSearchParams({});
}
};
return (
商品リスト
{/* フィルタリングボタン */}
<div>
<button onClick={() => handleFilterChange(null)}>全カテゴリ</button>
<button onClick={() => handleFilterChange('electronics')}>電化製品</button>
<button onClick={() => handleFilterChange('books')}>書籍</button>
</div>
{/* 商品一覧 */}
<ul>
{filteredProducts.map(product => (
<li key={product.id}>
{/* 個別商品詳細へのリンク(もしProductDetailルートがあるなら) */}
{/* <Link to={`/products/${product.id}`}>{product.name}</Link> */}
{product.name} ({product.category})
</li>
))}
</ul>
</div>
);
}
export default ProductList;
“`
App.js にこの ProductList コンポーネントへのルートを追加します。
“`javascript
// src/App.js (一部変更)
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
// … 他のインポート …
import ProductList from ‘./components/ProductList’; // ProductListをインポート
function App() {
return (
<hr />
<Routes>
{/* ... 他のRoute ... */}
{/* 商品リストへのルート */}
{/* /products または /products?category=... にマッチ */}
<Route path="/products" element={<ProductList />} />
{/* ... ProductDetail ルートなど ... */}
</Routes>
</div>
</BrowserRouter>
);
}
“`
これで、/products にアクセスすると商品リストが表示されます。フィルタリングボタンをクリックすると、URLが /products?category=electronics のように変化し、それに合わせて ProductList コンポーネント内で useSearchParams から取得した category の値が変わるため、表示される商品リストもフィルタリングされます。
useSearchParams から返される URLSearchParams オブジェクトは、get('key')、getAll('key')、has('key')、toString() といったメソッドを持っており、クエリパラメーターの読み取りに便利です。
setSearchParams 関数は、引数にオブジェクトまたは関数を受け取り、クエリパラメーターを更新します。新しいクエリパラメーターを設定すると、URLが更新され、そのルートをレンダリングしているコンポーネントが再レンダリングされます。
プログラムによる画面遷移 (useNavigate)
ユーザーがリンクをクリックすることによる画面遷移だけでなく、プログラムの実行フローの中で自動的に別のページへ遷移させたい場面があります。例えば、フォームを送信した後に成功メッセージページへリダイレクトしたり、ユーザーがログインに成功したらダッシュボードへ移動させたりする場合です。
このような「プログラムによる画面遷移」を実現するために、React Router DOM v6では useNavigate フックが提供されています。useNavigate フックを呼び出すと、ナビゲーションを実行するための関数が返されます。
例を見てみましょう。簡単なログインフォームがあり、ログインボタンをクリックしたらダッシュボードページに遷移するようなシナリオを考えます。
まず、ログインフォームコンポーネント LoginForm.js を作成します。
“`javascript
// src/components/LoginForm.js
import React, { useState } from ‘react’;
import { useNavigate } from ‘react-router-dom’; // useNavigateフックをインポート
function LoginForm() {
const [username, setUsername] = useState(”);
const [password, setPassword] = useState(”);
// useNavigateフックを呼び出して、ナビゲーション関数を取得
const navigate = useNavigate();
const handleSubmit = (event) => {
event.preventDefault(); // フォームのデフォルト送信を防ぐ
// ここで実際の認証処理を行う(省略)
console.log('Login attempt with:', username, password);
// 認証成功と仮定して、ダッシュボードページへ遷移する
// navigate('/') または navigate('/dashboard') のように遷移先のパスを指定する
navigate('/'); // 例: ホームページへ遷移
// navigate('/dashboard'); // 例: ダッシュボードページへ遷移
};
return (
ログイン
);
}
export default LoginForm;
“`
次に、App.js に LoginForm へのルートを追加します。ダッシュボードへのルートも必要であれば追加しておきます(ここでは簡単のためホームに遷移しています)。
“`javascript
// src/App.js (一部変更)
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
// … 他のインポート …
import LoginForm from ‘./components/LoginForm’; // LoginFormをインポート
function App() {
return (
<hr />
<Routes>
{/* ... 他のRoute ... */}
{/* ログインページへのルート */}
<Route path="/login" element={<LoginForm />} />
{/* ダッシュボードなど、ログイン後に遷移する可能性のあるルートも定義しておく */}
{/* <Route path="/dashboard" element={<Dashboard />} /> */}
</Routes>
</div>
</BrowserRouter>
);
}
“`
これで、/login ページでユーザー名とパスワードを入力し、ログインボタンをクリックすると、handleSubmit 関数が実行され、その中の navigate('/')(または navigate('/dashboard') など)によってプログラム的に / パスへ画面遷移が行われます。
navigate 関数の使い方:
navigate 関数はいくつかの呼び出し方があります。
navigate('/path'): 指定したパスへ遷移します。ブラウザの履歴スタックに新しいエントリを追加します。これはhistory.push('/path')に相当します。navigate('/path', { replace: true }): 指定したパスへ遷移しますが、現在の履歴エントリを置き換えます。ブラウザの「戻る」ボタンで直前のページに戻れなくなります。これはログイン後のリダイレクトなど、ユーザーがログインページに戻るべきではない場合に便利です。history.replace('/path')に相当します。navigate(-1): 履歴を1つ戻ります。ブラウザの「戻る」ボタンを押すのと同じ挙動です。navigate(2): 履歴を2つ進みます。ブラウザの「進む」ボタンを押すのと同じ挙動です。navigate('/path', { state: { someData: value } }): 遷移先に状態データを渡すことができます。遷移先のコンポーネントではuseLocationフックを使ってlocation.stateからデータを取り出せます。
useNavigate フックもまた、コンポーネントが <Routes> の中の <Route> によってレンダリングされる階層、またはその子孫コンポーネントで使用する必要があります。
ネストされたルート (Nested Routes)
React Router DOM v6の強力な機能の一つに、ネストされたルート(入れ子になったルート)のサポートがあります。これは、特定の親ルートの下に複数の子ルートが存在する場合に非常に便利です。例えば、ダッシュボードの各セクション(設定、プロフィール、レポートなど)や、ブログのカテゴリ別記事一覧とその中の個別記事詳細などが典型的な例です。
ネストされたルートを使うと、親コンポーネント内で子ルートに対応するコンポーネントをレンダリングできます。これにより、共通のレイアウト(サイドバーやタブなど)を持つセクションを簡単に構築できます。
ネストされたルートを定義するには、<Route> コンポーネントを別の <Route> コンポーネントの中に子として配置します。そして、親の element に指定されたコンポーネント内で、子ルートがレンダリングされる場所として <Outlet> コンポーネントを配置します。
例として、ダッシュボードセクションのネストされたルートを考えます。ダッシュボードには「概要」「設定」「プロフィール」の3つのサブページがあるとします。
まず、各サブページのコンポーネントを作成します。
“`javascript
// src/components/DashboardSummary.js
import React from ‘react’;
function DashboardSummary() {
return (
概要
ダッシュボードの概要情報が表示されます。
);
}
export default DashboardSummary;
// src/components/DashboardSettings.js
import React from ‘react’;
function DashboardSettings() {
return (
設定
ユーザー設定をここで行います。
);
}
export default DashboardSettings;
// src/components/DashboardProfile.js
import React from ‘react’;
function DashboardProfile() {
return (
プロフィール
ユーザープロフィールが表示されます。
);
}
export default DashboardProfile;
“`
次に、これらのサブページをラップする親コンポーネント DashboardLayout.js を作成します。このコンポーネントには共通のナビゲーションやレイアウト要素を含め、子ルートの内容が表示される場所に <Outlet> を配置します。
“`javascript
// src/components/DashboardLayout.js
import React from ‘react’;
import { Link, Outlet } from ‘react-router-dom’; // LinkとOutletをインポート
function DashboardLayout() {
return (
ダッシュボード
{/ ダッシュボード共通のサブナビゲーション /}
<hr />
{/* 子ルートがレンダリングされる場所 */}
{/* URLが /dashboard/settings なら <DashboardSettings /> がここに表示される */}
{/* URLが /dashboard/profile なら <DashboardProfile /> がここに表示される */}
{/* URLが /dashboard または /dashboard/ なら、親Routeのindex要素(下記参照)がここに表示される */}
<Outlet />
</div>
);
}
export default DashboardLayout;
“`
最後に、App.js の <Routes> の中に、ネストされたルートを定義します。
“`javascript
// src/App.js (一部変更)
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
// … 他のインポート …
import DashboardLayout from ‘./components/DashboardLayout’; // 親コンポーネントをインポート
import DashboardSummary from ‘./components/DashboardSummary’; // 子コンポーネントをインポート
import DashboardSettings from ‘./components/DashboardSettings’;
import DashboardProfile from ‘./components/DashboardProfile’;
function App() {
return (
<hr />
<Routes>
{/* ... 他のRoute ... */}
{/* ダッシュボードの親ルート */}
{/* path="/dashboard" にマッチしたら <DashboardLayout /> をレンダリング */}
<Route path="/dashboard" element={<DashboardLayout />}>
{/* ここにネストされた子ルートを定義 */}
{/* index属性を持つRouteは、親パス (/dashboard) に正確にマッチした場合にレンダリングされる */}
{/* /dashboard または /dashboard/ の場合に <DashboardSummary /> を表示 */}
<Route index element={<DashboardSummary />} />
{/* path="settings" は相対パス。親のパス (/dashboard) と組み合わされて /dashboard/settings になる */}
<Route path="settings" element={<DashboardSettings />} />
{/* path="profile" も相対パス。親のパス (/dashboard) と組み合わされて /dashboard/profile になる */}
<Route path="profile" element={<DashboardProfile />} />
{/* 子ルートにマッチしなかった場合のフォールバックも設定可能 */}
{/* <Route path="*" element={<DashboardNotFound />} /> */}
</Route>
</Routes>
</div>
</BrowserRouter>
);
}
“`
この設定により、以下のようになります。
- URLが
/dashboardまたは/dashboard/の場合:<Routes>はpath="/dashboard"の<Route>にマッチします。DashboardLayoutコンポーネントがレンダリングされます。DashboardLayout内の<Outlet>の場所には、子ルートの中でindex属性を持つ<Route index element={<DashboardSummary />} />のelementである<DashboardSummary />がレンダリングされます。
- URLが
/dashboard/settingsの場合:<Routes>はpath="/dashboard"の親<Route>にマッチします。DashboardLayoutコンポーネントがレンダリングされます。- 同時に、親パス
/dashboardの下の子ルートのうち、path="settings"の<Route>がマッチします。 DashboardLayout内の<Outlet>の場所には、この子ルートのelementである<DashboardSettings />がレンダリングされます。
- URLが
/dashboard/profileの場合も同様に、DashboardProfileが<Outlet>の場所にレンダリングされます。
ネストされたルートの <Link> の to プロパティでは、親ルートからの相対パスを指定するのが一般的です(例: "settings", "profile")。ルートパス(/dashboard自体)を指したい場合は、v6では "." を使用します (<Link to=".">)。以前のバージョンでは "" (空文字列) を使うことが多かったですが、v6からは "." が推奨されています。絶対パス (/dashboard/settings) を指定することも可能ですが、相対パスを使うことで、親ルートのパスが変更されても子ルート側の to プロパティを変更する必要がなくなるというメリットがあります。
index ルート (<Route index element={<... />} />) は、親ルートのパスに正確にマッチした場合にレンダリングされる特別な子ルートです。親ルートがパスを指定している場合、index 子ルートは親パスのデフォルトコンテンツとして機能します。
ネストされたルートと <Outlet> を使うことで、共通レイアウトを持つ複雑なアプリケーション構造を、より直感的かつコンポーネント指向で記述できるようになります。
404ページの作成
ユーザーがアプリケーションに存在しないURLにアクセスした場合(例: タイプミスや古いリンクなど)、適切な「404 Not Found」ページを表示するのがユーザー体験上望ましいです。
React Router DOMでは、これを簡単に実装できます。<Routes> コンポーネントは、子として定義された <Route> を上から順に評価し、現在のURLに最初にマッチした Route をレンダリングします。この特性を利用して、すべてのルート定義の 最後に path="*" というワイルドカードパスを持つ <Route> を配置します。
path="*" は、それより前に定義されたどのパスにもマッチしなかった場合にマッチします。したがって、これを404ページ用のルートとして使用できます。
まず、404ページ用のコンポーネントを作成します。
“`javascript
// src/components/NotFoundPage.js
import React from ‘react’;
import { useLocation } from ‘react-router-dom’; // 現在のパスを表示するために使用
function NotFoundPage() {
const location = useLocation(); // 現在のロケーション情報を取得
return (
404 – ページが見つかりません
{location.pathname} というパスのページは見つかりませんでした。
{/ ホームへ戻るリンクなどを追加しても良い /}
{/ ホームに戻る /}
);
}
export default NotFoundPage;
“`
次に、App.js の <Routes> の中の、他のすべての <Route> の定義よりも後ろに、この NotFoundPage へのルートを追加します。
“`javascript
// src/App.js (一部変更)
import React from ‘react’;
import { BrowserRouter, Routes, Route, Link } from ‘react-router-dom’;
// … 他のインポート …
import NotFoundPage from ‘./components/NotFoundPage’; // NotFoundPageをインポート
function App() {
return (
<hr />
<Routes>
{/* 通常のルート定義 */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/products/:productId" element={<ProductDetail />} />
<Route path="/products" element={<ProductList />} />
<Route path="/login" element={<LoginForm />} />
{/* ネストされたルートもここより前に配置 */}
<Route path="/dashboard" element={<DashboardLayout />}>
{/* ... 子Route ... */}
</Route>
{/* --- ここからが重要 --- */}
{/* どのパスにもマッチしなかった場合に、このルートがマッチする */}
{/* 必ず Routes の最後の方に配置する */}
<Route path="*" element={<NotFoundPage />} />
</Routes>
</div>
</BrowserRouter>
);
}
“`
これで、定義されたどのパスにもマッチしないURLにアクセスがあった場合、path="*" のルートがマッチし、NotFoundPage コンポーネントがレンダリングされます。
useLocation フックは、現在のURLに関する情報(パス名、クエリ文字列、ハッシュなど)を含む location オブジェクトを返します。404ページで、見つからなかったパスを表示するのに便利です。
NavLink を使ったアクティブリンクのスタイリング
ナビゲーションバーを作成する際に、ユーザーが現在どのページを見ているかを視覚的に分かりやすくするために、アクティブなリンク(現在表示されているページのリンク)に特別なスタイルを適用したい場合があります。例えば、背景色を変えたり、下線を引いたりするなどです。
React Router DOMは、この目的のために NavLink という特別なコンポーネントを提供しています。NavLink は <Link> とほぼ同じように使えますが、現在のURLが to プロパティのパスにマッチしている場合に、特定のCSSクラスを適用したり、インラインスタイルを適用したりする機能が追加されています。
NavLink を使うと、アクティブな状態かどうかを判定して手動でクラスを切り替えるロジックを書く必要がなく、宣言的にアクティブスタイルを適用できます。
例として、先ほどのナビゲーションバーの <Link> を <NavLink> に置き換えてみましょう。
“`javascript
// src/App.js (一部変更)
import React from ‘react’;
import { BrowserRouter, Routes, Route, NavLink } from ‘react-router-dom’; // LinkではなくNavLinkをインポート
// … 他のインポート …
function App() {
// アクティブなスタイルを定義
// isActive 引数は、現在のNavLinkがアクティブかどうかを示す真偽値
const activeStyle = {
textDecoration: “underline”,
color: “#007bff”, // 例: 青色に
};
// またはクラス名を適用する場合
const activeClassName = “active-link”;
return (
<hr />
<Routes>{/* ... Routeの定義 ... */}</Routes>
</div>
</BrowserRouter>
);
}
export default App;
“`
NavLink の style プロパティにオブジェクトではなく関数を渡しているのがポイントです。この関数は引数として { isActive } というオブジェクトを受け取ります。isActive は現在の NavLink の to プロパティのパスが現在のURLとマッチしている場合に true になります。この isActive の値に基づいて、アクティブ時のスタイルオブジェクトを返す(または非アクティブ時は undefined を返す)ことで、スタイルを動的に適用できます。
同様に、className プロパティにも関数を渡すことで、アクティブな場合に特定のCSSクラス名を適用し、それに基づいてスタイルを定義することもできます。
NavLinkのデフォルトのアクティブクラス:
NavLink は、デフォルトでアクティブなリンクに対して active というCSSクラス名を適用します。CSS側で .active または .active-link のようなセレクタを使ってスタイルを定義することで、簡単にアクティブスタイルを設定できます。
“`css
/ 例: src/App.css または別のCSSファイル /
.active {
text-decoration: underline;
font-weight: bold;
color: #007bff;
}
/ もし className={({ isActive }) => (isActive ? “my-active-class” : “”)} のように使った場合 /
.my-active-class {
/ スタイルを定義 /
}
“`
CSSクラスを使う方法は、スタイルをCSSファイルに集約できるため、より一般的で管理しやすいです。
NavLink は、アクティブ判定において、指定された to パスが現在のURLの先頭部分と一致するかどうかを見ます。例えば、/products という NavLink は、/products だけでなく /products/123 というURLにもマッチしてアクティブになります。もし、特定のパスに「完全に一致する場合のみ」アクティブにしたい場合は、end プロパティを true に設定します (<NavLink to="/products" end>)。v6では、親ルートの index ルート (/dashboard 自体) に対応する NavLink は、to="." と end を一緒に使うのが一般的です。
よくある疑問とトラブルシューティング
React Router DOMを使い始めた際に、いくつか戸惑いやすい点やよくあるエラーがあります。
-
「
useNavigateやuseParamsなどのフックが使えない」というエラー:- 原因: これらのフックは、
BrowserRouter(または他のルータープロバイダー) のコンテキスト内でレンダリングされるコンポーネントでしか使用できません。 - 解決策: アプリケーション全体、またはフックを使用したいコンポーネントが含まれるツリーの最上位を
<BrowserRouter>でラップしていることを確認してください。通常はsrc/index.js(またはmain.jsx) で<App />を<BrowserRouter>で囲みます。
- 原因: これらのフックは、
-
「リンクをクリックしてもページが再読み込みされてしまう」:
- 原因:
react-router-domの<Link>コンポーネントではなく、HTML標準の<a href="...">タグを使用している可能性があります。 - 解決策: SPA内部のナビゲーションには必ず
<Link to="...">または<NavLink to="...">を使用してください。外部サイトへのリンクの場合は<a href="..." target="_blank">のようなHTMLタグを使用します。
- 原因:
-
「意図しないルートがマッチしてしまう」:
- 原因:
<Route>コンポーネントが<Routes>の外に定義されている、またはv6以前のexactプロパティの考え方が残っている可能性があります。v6では<Routes>が最適なマッチングを行います。 - 解決策: すべての
<Route>は必ず<Routes>の子として定義してください。また、v6では基本的にexactは不要です。path="/"は/にのみマッチし、/aboutや/contactにはマッチしません。より限定的なパス(例:/products/123)は、より一般的なパス(例:/productsや/)よりも優先的にマッチします。
- 原因:
-
「URLパラメーター (
useParams) が取得できない」:- 原因:
<Route path>でパラメーターが正しく定義されていない(例:path="/products/:productId"となっているか)、またはuseParams()を呼び出しているコンポーネントが、そのパラメーターを含む<Route>によってレンダリングされていない可能性があります。 - 解決策:
Routeのpathに:parameterNameの形式でパラメーターを正しく定義し、useParamsを呼び出しているコンポーネントが、そのRouteのelementとして直接、または親ルートの<Outlet>を通じてレンダリングされていることを確認してください。useParamsから取得する際のキー名は、pathで定義した:parameterNameから:を除いた名前 (parameterName) と一致させる必要があります。
- 原因:
-
React Router v5 から v6 への移行で困っている:
- v6ではいくつかの重要な変更点があります。
Switch->Routes: ルート定義のコンテナがSwitchからRoutesに変わりました。component/render->element:<Route>でレンダリングする要素を指定するプロパティがcomponentやrenderからelementに変更され、<ComponentName />の形式で指定するようになりました。useHistory->useNavigate: プログラムによる遷移のためのフックがuseHistoryからuseNavigateに変わりました。使い方も少し異なります。exactプロパティは基本的に不要になりました。- ネストされたルートの定義方法や、子ルートをレンダリングする
<Outlet>コンポーネントが導入されました。 - 相対パスの扱い方が変わりました (
.や..で親や祖先のパスを指定)。
- 解決策: 公式ドキュメントの移行ガイド (Migration Guide) を参照するか、v6の記法に合わせてコードを書き直してください。この記事はv6を前提に書かれているため、参考にしてください。
- v6ではいくつかの重要な変更点があります。
これらの点に注意しながらコードを書くことで、React Router DOMをスムーズに使いこなせるようになるはずです。
より発展的なトピック(簡単な触りだけ)
この記事ではReact Router DOMの基本に焦点を当てましたが、実際にはさらに多くの機能や応用方法があります。ここではいくつか簡単な触りだけ紹介します。
- レイアウトルート (Layout Routes): ネストされたルートと
Outletを使うことで、ヘッダー、サイドバー、フッターなどの共通レイアウトの中に子ルートの内容を表示する構造を簡単に構築できます。これは非常に一般的なSPAのパターンです。 - 認証・認可によるルートガード (Protected Routes): 特定のページ(例: ユーザー設定、管理画面)にアクセスできるユーザーを制限したい場合があります。これは、現在のユーザーがログインしているか、必要な権限を持っているかを確認し、条件を満たさない場合はログインページやエラーページにリダイレクトする処理をルート定義に組み込むことで実現できます。通常は、ログイン状態をチェックするラッパーコンポーネントを作成し、その中で
useNavigateや<Navigate>コンポーネント(特定の条件が満たされた場合にリダイレクトを行うコンポーネント)を使用します。 -
Code Splitting (コード分割) と組み合わせる: アプリケーションの規模が大きくなると、すべてのコンポーネントのJavaScriptコードを最初のページロード時にまとめてダウンロードするのは非効率です。React Router DOMとReactの
React.lazy()およびSuspenseを組み合わせることで、特定のルートにアクセスがあったときに初めてそのルートに対応するコンポーネントのコードを遅延ロード(分割ロード)させることができます。これにより、初期ロード時間を短縮できます。
“`javascript
import React, { lazy, Suspense } from ‘react’;
import { BrowserRouter, Routes, Route } from ‘react-router-dom’;// コンポーネントを遅延ロード
const LazyAbout = lazy(() => import(‘./components/About’));
const LazyContact = lazy(() => import(‘./components/Contact’));function App() {
return (
{/ 遅延ロードされるコンポーネントが表示されるまでのフォールバックUI /}
Loading…\
}>
{/ lazyでインポートしたコンポーネントをelementに指定 /}
);
}
``useScrollRestoration` フックを使うことで、この挙動を制御できます。
* **スクロールの復元 (Scroll Restoration):** ページ遷移後、多くの場合ページの上部にスクロールしたいですが、ブラウザの「戻る」ボタンで前のページに戻ったときは、元のスクロール位置に戻りたいはずです。React Router DOMの
これらの発展的なトピックについては、React Router DOMの公式ドキュメントや、より詳細な解説記事を参照することをおすすめします。しかし、まずはこの記事で解説した基本的な使い方をしっかりとマスターすることが、これらの応用に進むための第一歩です。
まとめ
この記事では、Reactアプリケーションにクライアントサイドルーティングを導入するための標準ライブラリである React Router DOM について、その必要性から基本的な使い方、そして主要な機能までを詳しく解説しました。
- SPAにおけるスムーズな画面遷移とURL・履歴管理の課題を解決するのがクライアントサイドルーティングです。
- React Router DOMは、
BrowserRouter、Routes、Route、Linkといったコンポーネントを使って、宣言的にルーティングを設定できます。 BrowserRouterはアプリケーション全体をラップし、ブラウザの履歴APIとの連携を担います。Routesは複数のRouteを管理し、現在のURLにマッチする最適なRouteをレンダリングします。Routeは特定のパスと表示する要素(コンポーネント)を関連付けます。LinkはSPA内でのページ再読み込みなしのナビゲーションリンクを作成します。useParamsフックでURLパラメーターを取得し、動的なコンテンツ表示に利用できます。useSearchParamsフックでクエリパラメーターを読み書きし、リストのフィルタリングなどに利用できます。useNavigateフックで、プログラムによる画面遷移(リダイレクトなど)を実行できます。- ネストされたルートと
Outletコンポーネントを使うことで、共通レイアウトを持つ複雑なページ構造を効率的に構築できます。 path="*"の<Route>を使って404ページを実装できます。NavLinkを使うと、アクティブなリンクに自動的にスタイルを適用できます。
React Router DOMは非常に柔軟で強力なライブラリであり、これらの基本的な要素を理解すれば、ほとんどのSPAで必要とされるルーティング機能を実装できるようになります。
まずは小さなアプリケーションで実際にこれらのコンポーネントを使ってみることから始めてください。コードを書き、ブラウザで挙動を確認し、エラーに遭遇したら原因を探るというプロセスを通じて、理解が深まります。
次のステップ
- この記事のコード例を実際に自分のReactプロジェクトで試してみる。
- 簡単なブログアプリケーションや商品リスト/詳細ページのようなものを、今回学んだ機能を使って実装してみる。
- React Router DOMの公式ドキュメント(https://reactrouter.com/docs/)を参照し、さらに詳しい情報や高度な機能について学ぶ。
- React Router DOMを使った認証付きルートやコード分割などの応用例について調べてみる。
React Router DOMをマスターして、あなたのReactアプリケーションに強力なナビゲーション機能を実装しましょう!