react-router-domとreact-router v7

概要

viteでreactのプロジェクトを作成すると、react-router-domの7系がセットアップされます。

これでも問題なく使えますが、公式ドキュメントではreact-router-domを削除し、react-routerをインストールすることを推奨しています。

https://react-router-docs-ja.techtalk.jp/upgrading/v6#v7-%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B

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より順次移行する必要があります。

ルーティング記述方法3種類

react-routerには記述方法が3種類あります。Declarative, Data, Frameworkです。

DeclarativeからData、そしてFrameworkへと移行すると、アーキテクチャの制御と引き換えに、より多くの機能が追加されます。したがって、React Routerからどれだけの制御または支援が必要かに基づいてモードを選択してください。

https://react-router-docs-ja.techtalk.jp/start/modes#%E9%81%B8%E6%8A%9E%E3%81%AE%E3%82%A2%E3%83%89%E3%83%90%E3%82%A4%E3%82%B9

以下は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>
  );
}