viteでreactのプロジェクトを作成すると、react-router-domの7系がセットアップされます。
これでも問題なく使えますが、公式ドキュメントではreact-router-domを削除し、react-routerをインストールすることを推奨しています。
The react-router-dom, @remix-run/react, @remix-run/server-runtime, and @remix-run/router have been collapsed into the react-router package
react-router-domなどはreact-routerに内包されたようで、react-router-domでも今まで通りの表記が可能となりますが、import元を変更する必要があります。
react-router-dom
↓
react-router/dom
To ease migration, react-router-dom is still published in v7 as a re-export of everything from react-router
なぜreact-router-dom v7があるのかというと移行を容易にするためとのことです。
https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#package-restructuring
結論として、react-routerの7系を使う場合は、react-router-domより順次移行する必要があります。
react-routerには記述方法が3種類あります。Declarative, Data, Frameworkです。
DeclarativeからData、そしてFrameworkへと移行すると、アーキテクチャの制御と引き換えに、より多くの機能が追加されます。したがって、React Routerからどれだけの制御または支援が必要かに基づいてモードを選択してください。
以下はDeclarativeモードの一例です。
DeclarativeモードではBrowserRouterを使います。
import './App.css'
import { BrowserRouter } from 'react-router'
import { Routes, Route } from 'react-router'
import { AuthProvider } from './contexts/AuthContext'
import MainLayout from './layouts/MainLayout'
import Dashboard from './pages/Dashboard'
import Users from './pages/Users'
import Settings from './pages/Settings'
import Login from './pages/Login'
import PublicRoute from './components/PublicRoute'
import ProtectedRoute from './components/ProtectedRoute'
export default function App() {
return (
<AuthProvider>
<BrowserRouter>
<Routes>
<Route element={<PublicRoute />}>
<Route path="/login" element={<Login />} />
</Route>
<Route element={<ProtectedRoute />}>
<Route path="/" element={<MainLayout />}>
<Route index element={<Dashboard />} />
<Route path="users" element={<Users />} />
<Route path="settings" element={<Settings />} />
</Route>
</Route>
</Routes>
</BrowserRouter>
</AuthProvider>
);
}
以下はDataモードの一例です。
DataモードはcreateBrowserRouterを使います。
import './App.css';
import { createBrowserRouter, RouterProvider, redirect } from 'react-router';
import { AuthProvider, useAuth } from './contexts/AuthContext';
import MainLayout from './layouts/MainLayout';
import Dashboard from './pages/Dashboard';
import Users from './pages/Users';
import Settings from './pages/Settings';
import Login from './pages/Login';
// 認証チェックのためのLoader関数
const protectedLoader = () => {
// loader関数では useAuth が使えないのでここではダミーの認証チェック
// 実際の実装では getAuthStatus などの非Hook関数を使う必要があります
const isAuthenticated = localStorage.getItem('isAuthenticated') === 'true';
if (!isAuthenticated) {
return redirect('/login');
}
return null;
};
const publicLoader = () => {
const isAuthenticated = localStorage.getItem('isAuthenticated') === 'true';
if (isAuthenticated) {
return redirect('/');
}
return null;
};
// ルーターの設定
const router = createBrowserRouter([
{
path: "/login",
element: <Login />,
loader: publicLoader,
},
{
path: "/",
element: <MainLayout />,
loader: protectedLoader,
children: [
{
index: true,
element: <Dashboard />,
},
{
path: "users",
element: <Users />,
loader: async () => {
// ここでユーザーデータをフェッチする例
// const response = await fetch('/api/users');
// return response.json();
return { users: [] }; // サンプルデータ
},
},
{
path: "settings",
element: <Settings />,
},
],
},
]);
export default function App() {
return (
<AuthProvider>
<RouterProvider router={router} />
</AuthProvider>
);
}