🐷

[react-router-dom v6]ログイン状態に応じてルート設定したい

2024/02/10に公開

解決したい問題

ログインしていないユーザーはログイン画面にリダイレクトするように、React Router v6でルート設定を行いたいです。

下記の例のように各ルートごとに設定してもよいのですが、ルートが増えるに従いコードが冗長になります。

<Route
  path="/secret"
  element={
    <ProtectedRoute> // ここでログイン状態を判定する
      <Secret />
    </ProtectedRoute>
  }
/>

ログイン状態にかかわらずアクセスできるルート(Publicルート)、ログインユーザーのみアクセスできるルート(Privateルート)をまとめて設定する構成にしたいです。

結論

レイアウトルートをPublic用とPrivate用にそれぞれ用意します。

環境

  • node 20.9.0
  • Vite 5.1.1
  • React 18.2.0
  • TypeScript 5.3.3
  • react-router-dom 6.22.0

Code Sandbox:

レイアウトルートの作成

Publicレイアウト

Outletでリンク先要素を表示します。

src\layout\PublicLayout.tsx
export default function PublicLayout() {
  return <Outlet />;
}

Privateレイアウト

ログイン済みならリンク先を表示。

ログインしていなければログインページにリダイレクトします。

src\layout\PrivateLayout.tsx
export default function PrivateLayout() {
  const { loggedIn } = useAuthContext();
  if (!loggedIn) {
    return <Navigate to="/login" />;
  }
  return <Outlet />;
}

ルートの定義

アクセスを制限したいルートをPrivateレイアウトルートで囲みます。

src\App.tsx
<Routes>
  {/* public routes */}
  <Route element={<PublicLayout />}>
    <Route path="/" element={<PublicPage />} />
    <Route path="/login" element={<LoginPage />} />
  </Route>
  {/* private routes */}
  <Route element={<PrivateLayout />}>
    <Route path="/private" element={<PrivatePage />} />
  </Route>
</Routes>

参考文献

Discussion