はい、承知いたしました。React Router v6を徹底解説する記事を約5000語で記述します。
React Router v6徹底解説:SPAの画面遷移をマスターしよう
シングルページアプリケーション (SPA) の開発において、画面遷移の制御は重要な要素です。React Router は、React アプリケーションで宣言的なルーティングを実現するためのライブラリであり、SPA の構築を容易にします。この記事では、React Router v6 の基本的な概念から高度なテクニックまでを網羅的に解説し、SPA の画面遷移をマスターするための知識を提供します。
目次
-
React Router とは?
- 1.1. SPA とルーティングの必要性
- 1.2. React Router の役割と利点
- 1.3. React Router v6 の主な変更点
-
React Router v6 の基本
- 2.1. インストールとセットアップ
- 2.2.
<BrowserRouter>
: ブラウザの履歴を使用するルーティング - 2.3.
<Routes>
と<Route>
: ルートの定義とマッチング - 2.4.
<Link>
: ページ遷移のためのコンポーネント - 2.5.
useNavigate
: プログラムによる画面遷移
-
パスパラメータとクエリパラメータ
- 3.1. パスパラメータ: 動的な URL の定義
- 3.2.
useParams
: パスパラメータの取得 - 3.3. クエリパラメータ: URL に付加的な情報を付与
- 3.4.
useSearchParams
: クエリパラメータの操作
-
ネストされたルーティング
- 4.1. 子ルートの定義
- 4.2.
<Outlet>
: 子コンポーネントの表示場所 - 4.3. 相対パスと絶対パス
-
高度なルーティングテクニック
- 5.1. リダイレクト: 特定の URL への自動遷移
- 5.2.
useLocation
: 現在の URL 情報の取得 - 5.3. 認証 (Authentication) の実装
- 5.4. 遅延ローディング (Lazy Loading)
- 5.5. カスタムフックの作成
-
React Router v6 の実践的な活用例
- 6.1. E コマースサイトのルーティング設計
- 6.2. ブログサイトのルーティング設計
- 6.3. ダッシュボードアプリケーションのルーティング設計
-
React Router v6 のトラブルシューティング
- 7.1. ルートがマッチしない場合の対処法
- 7.2. ブラウザの履歴が正しく動作しない場合の対処法
- 7.3. その他のよくある問題と解決策
-
まとめ
1. React Router とは?
1.1. SPA とルーティングの必要性
シングルページアプリケーション (SPA) は、Web ページ全体をリロードせずにコンテンツを動的に更新する Web アプリケーションです。従来のマルチページアプリケーション (MPA) とは異なり、SPA は初期ロード時に必要なリソース (HTML, CSS, JavaScript) をすべてダウンロードし、その後は JavaScript を使用して DOM を操作することで、ユーザーに滑らかな操作感を提供します。
SPA では、ユーザーが異なる画面に遷移するたびに、サーバーにリクエストを送信して新しい HTML を取得するのではなく、JavaScript によって画面の一部または全体を更新します。この画面遷移を制御する仕組みがルーティングです。ルーティングは、URL に基づいてどのコンポーネントを表示するかを決定し、SPA のナビゲーションを実現します。
1.2. React Router の役割と利点
React Router は、React アプリケーションで宣言的なルーティングを実装するためのライブラリです。URL とコンポーネントの対応を定義し、ユーザーが URL を変更した際に適切なコンポーネントを表示する役割を担います。
React Router を使用する主な利点は以下の通りです。
- 宣言的なルーティング: URL とコンポーネントの対応をコードで明示的に記述できるため、ルーティングの構造が理解しやすく、保守性が向上します。
- コンポーネントベース: React のコンポーネントとしてルーティングを定義できるため、React のエコシステムと親和性が高いです。
- 柔軟性: さまざまなルーティングパターンに対応しており、複雑なアプリケーションの要件にも対応できます。
- ブラウザの履歴管理: ブラウザの履歴 (history API) を使用して、SPA でもブラウザの「戻る」「進む」ボタンが正しく動作するように管理します。
- パフォーマンス: SPA の特性を活かし、必要なコンポーネントのみをレンダリングすることで、パフォーマンスを向上させます。
1.3. React Router v6 の主な変更点
React Router v6 は、従来のバージョンからいくつかの重要な変更が加えられています。主な変更点は以下の通りです。
<Switch>
の廃止と<Routes>
の導入:<Switch>
コンポーネントが廃止され、<Routes>
コンポーネントが導入されました。<Routes>
は、<Route>
コンポーネントをラップし、最適なルートを自動的に選択します。- 相対
<Link>
の強化:<Link>
コンポーネントが、より直感的で柔軟な相対パスをサポートするようになりました。 - Hooks API の改善:
useHistory
がuseNavigate
に、useLocation
が機能強化されました。より使いやすく、効率的なルーティング処理が可能になりました。 - ネストされたルーティングの簡略化:
<Outlet>
コンポーネントを使用することで、ネストされたルーティングがよりシンプルに記述できるようになりました。
2. React Router v6 の基本
2.1. インストールとセットアップ
React Router v6 をインストールするには、以下のコマンドを実行します。
“`bash
npm install react-router-dom@6
または
yarn add react-router-dom@6
“`
インストールが完了したら、アプリケーションのエントリーポイント (通常は index.js
または App.js
) で、React Router をセットアップします。
2.2. <BrowserRouter>
: ブラウザの履歴を使用するルーティング
<BrowserRouter>
コンポーネントは、ブラウザの履歴 API を使用してルーティングを管理します。<BrowserRouter>
でラップされたコンポーネントは、URL の変更に応じて再レンダリングされ、画面遷移が実現されます。
“`jsx
import { BrowserRouter } from ‘react-router-dom’;
function App() {
return (
{/ 他のコンポーネント /}
);
}
export default App;
“`
2.3. <Routes>
と <Route>
: ルートの定義とマッチング
<Routes>
コンポーネントは、複数の <Route>
コンポーネントをラップし、現在の URL に最適なルートを自動的に選択します。<Route>
コンポーネントは、URL パスと表示するコンポーネントの対応を定義します。
“`jsx
import { Routes, Route } from ‘react-router-dom’;
import Home from ‘./pages/Home’;
import About from ‘./pages/About’;
import Contact from ‘./pages/Contact’;
function App() {
return (
);
}
export default App;
“`
この例では、URL が /
の場合、<Home>
コンポーネントが表示され、/about
の場合は <About>
コンポーネント、/contact
の場合は <Contact>
コンポーネントが表示されます。
2.4. <Link>
: ページ遷移のためのコンポーネント
<Link>
コンポーネントは、ページ遷移を行うためのコンポーネントです。to
プロパティに遷移先の URL を指定します。<Link>
は、<a>
タグをラップし、SPA におけるクライアントサイドのナビゲーションを提供します。
“`jsx
import { Link } from ‘react-router-dom’;
function Navigation() {
return (
);
}
export default Navigation;
“`
2.5. useNavigate
: プログラムによる画面遷移
useNavigate
フックは、プログラムによって画面遷移を行うための関数を提供します。例えば、フォームの送信後に特定のページにリダイレクトしたり、条件に応じて異なるページに遷移させたりする場合に使用します。
“`jsx
import { useNavigate } from ‘react-router-dom’;
function Login() {
const navigate = useNavigate();
const handleSubmit = (event) => {
event.preventDefault();
// ログイン処理
if (/ ログイン成功 / true) {
navigate(‘/dashboard’);
} else {
// エラー処理
}
};
return (
);
}
export default Login;
“`
3. パスパラメータとクエリパラメータ
3.1. パスパラメータ: 動的な URL の定義
パスパラメータは、URL の一部を動的に変化させるための仕組みです。例えば、ユーザー ID や商品 ID などを URL に含める場合に便利です。パスパラメータは、<Route>
の path
プロパティで :
を使用して定義します。
jsx
<Route path="/users/:userId" element={<UserProfile />} />
この例では、/users/123
や /users/456
のように、/users/
の後に続く値を userId
というパスパラメータとして取得できます。
3.2. useParams
: パスパラメータの取得
useParams
フックは、現在の URL に含まれるパスパラメータを取得するためのフックです。useParams
を使用すると、userId
の値を <UserProfile>
コンポーネント内で取得できます。
“`jsx
import { useParams } from ‘react-router-dom’;
function UserProfile() {
const { userId } = useParams();
return (
User Profile
User ID: {userId}
);
}
export default UserProfile;
“`
3.3. クエリパラメータ: URL に付加的な情報を付与
クエリパラメータは、URL の末尾に ?
を付けて、付加的な情報を渡すための仕組みです。例えば、検索キーワードやページ番号などを URL に含める場合に便利です。
/products?category=electronics&page=2
この例では、category
と page
というクエリパラメータが含まれています。
3.4. useSearchParams
: クエリパラメータの操作
useSearchParams
フックは、クエリパラメータを取得および操作するためのフックです。useSearchParams
を使用すると、クエリパラメータの値を取得したり、新しいクエリパラメータを追加したり、既存のクエリパラメータを更新したりできます。
“`jsx
import { useSearchParams } from ‘react-router-dom’;
function ProductList() {
const [searchParams, setSearchParams] = useSearchParams();
const category = searchParams.get(‘category’);
const page = searchParams.get(‘page’);
const handleCategoryChange = (newCategory) => {
setSearchParams({ category: newCategory, page: 1 });
};
return (
Product List
Category: {category}
Page: {page}
<button onClick={() => handleCategoryChange('electronics')}>Electronics</button>
<button onClick={() => handleCategoryChange('clothing')}>Clothing</button>
</div>
);
}
export default ProductList;
“`
4. ネストされたルーティング
4.1. 子ルートの定義
ネストされたルーティングは、親ルートの下にさらに子ルートを定義する仕組みです。例えば、/users/:userId
の下に /users/:userId/profile
や /users/:userId/settings
などの子ルートを定義できます。
jsx
<Route path="/users/:userId" element={<UserLayout />}>
<Route path="profile" element={<UserProfile />} />
<Route path="settings" element={<UserSettings />} />
</Route>
4.2. <Outlet>
: 子コンポーネントの表示場所
<Outlet>
コンポーネントは、親コンポーネント内で子コンポーネントを表示する場所を指定します。<Outlet>
は、子ルートにマッチするコンポーネントをレンダリングします。
“`jsx
import { Outlet } from ‘react-router-dom’;
function UserLayout() {
return (
User Layout
{/ 子コンポーネントを表示する場所 /}
);
}
export default UserLayout;
“`
4.3. 相対パスと絶対パス
ネストされたルーティングでは、相対パスと絶対パスを使い分けることが重要です。相対パスは、現在のルートを基準としたパスであり、絶対パスは、ルートドメインを基準としたパスです。
- 相対パス:
profile
は、/users/:userId
を基準としたパスであり、/users/:userId/profile
にマッチします。 - 絶対パス:
/profile
は、ルートドメインを基準としたパスであり、/profile
にマッチします。
<Link>
コンポーネントで相対パスを使用する場合は、to
プロパティに ./profile
のように記述します。
5. 高度なルーティングテクニック
5.1. リダイレクト: 特定の URL への自動遷移
リダイレクトは、特定の URL にアクセスした際に、自動的に別の URL に遷移させるための仕組みです。例えば、ログインしていないユーザーをログインページにリダイレクトしたり、古い URL から新しい URL にリダイレクトしたりする場合に使用します。
React Router v6 では、Navigate
コンポーネントを使用してリダイレクトを実現します。
“`jsx
import { Navigate } from ‘react-router-dom’;
function ProtectedRoute({ children, isAuthenticated }) {
if (!isAuthenticated) {
return
}
return children;
}
export default ProtectedRoute;
“`
この例では、isAuthenticated
が false
の場合、/login
にリダイレクトされます。
5.2. useLocation
: 現在の URL 情報の取得
useLocation
フックは、現在の URL に関する情報を取得するためのフックです。useLocation
を使用すると、URL のパス、クエリパラメータ、ハッシュなどを取得できます。
“`jsx
import { useLocation } from ‘react-router-dom’;
function PageViewTracker() {
const location = useLocation();
useEffect(() => {
// ページビューをトラッキングする処理
console.log(‘Page View:’, location.pathname);
}, [location]);
return null;
}
export default PageViewTracker;
“`
この例では、URL が変更されるたびに、console.log
に現在のパスが出力されます。
5.3. 認証 (Authentication) の実装
React Router を使用して認証を実装するには、以下の手順が必要です。
- 認証状態の管理: ユーザーがログインしているかどうかを判断するための状態を管理します。
- 認証ルートの作成: ログインが必要なページを保護するためのルートを作成します。
- リダイレクトの実装: ログインしていないユーザーをログインページにリダイレクトします。
上記の ProtectedRoute
コンポーネントは、認証ルートの一例です。
5.4. 遅延ローディング (Lazy Loading)
遅延ローディングは、アプリケーションの初期ロード時間を短縮するためのテクニックです。遅延ローディングを使用すると、特定のコンポーネントが必要になるまでロードを遅らせることができます。
React Router と React.lazy() を組み合わせることで、ルートに基づいてコンポーネントを遅延ロードできます。
“`jsx
import { lazy, Suspense } from ‘react’;
const Home = lazy(() => import(‘./pages/Home’));
const About = lazy(() => import(‘./pages/About’));
function App() {
return (
}>\