React Router v6 でのリダイレクト方法
React Router v6 では、リダイレクトの実装方法が v5 から大きく変更されました。この記事では、v6 での効果的なリダイレクト方法を詳しく解説します。
問題点
React Router v6 では、v5 で使用されていた Redirect
コンポーネントや Route
の render
プロパティが削除されました。以下のコードは v5 では動作しましたが、v6 ではエラーが発生します:
<Route render={() => <Navigate to="/" />} />
エラーメッセージ:
Property 'render' does not exist on type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.
解決策
1. Navigate
コンポーネントを使用する
React Router v6 では、Redirect
コンポーネントの代わりに Navigate
コンポーネントを使用します。
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/lab" element={<Lab />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
TIP
replace
プロパティを使用すると、ブラウザの履歴に現在のページを残さないため、ユーザーが「戻る」ボタンを押した際に余計なリダイレクトが発生しません。
2. 条件付きリダイレクト
ユーザーの認証状態などに基づいた条件付きリダイレクトも簡単に実装できます:
<Route
path="/login"
element={user ? <Navigate to="/" replace /> : <Login />}
/>
<Route
path="/dashboard"
element={user ? <Dashboard /> : <Navigate to="/login" replace />}
/>
3. カスタムリダイレクトコンポーネント
より複雑なリダイレクトが必要な場合、カスタムコンポーネントを作成できます:
import { useEffect } from 'react';
import { generatePath, useNavigate, useParams } from 'react-router-dom';
function Redirect({ to }: { to: string }) {
const navigate = useNavigate();
const params = useParams();
useEffect(() => {
navigate(generatePath(to, params), { replace: true });
}, [navigate, to, params]);
return null;
}
// 使用例
<Route path="/users/:id" element={<Redirect to="/new-path/:id" />} />
このコンポーネントは、パスパラメータを保持したままリダイレクトを行います(例: /users/10
→ /new-path/10
)。
4. プログラムによるリダイレクト
イベントハンドラー内でリダイレクトを行う場合は、useNavigate
フックを使用します:
import { useNavigate } from 'react-router-dom';
function MyComponent() {
const navigate = useNavigate();
const handleRedirect = () => {
navigate('/target-path', { replace: true });
};
return (
<button onClick={handleRedirect}>移動する</button>
);
}
認証ガードパターン
保護されたルートを実装する際は、高階コンポーネントパターンが便利です:
import { useLocation, Navigate } from 'react-router-dom';
import { useAuth } from '../hooks/Auth';
export function RequireAuth({ children }: { children: JSX.Element }) {
let { user } = useAuth();
let location = useLocation();
if (!user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
}
// 使用例
<Route
path="/dashboard"
element={
<RequireAuth>
<Dashboard />
</RequireAuth>
}
/>
よくある間違いと回避策
WARNING
Navigate
コンポーネントを条件なしで直接レンダリングすると、無限ループが発生する可能性があります。条件付きレンダリングや useEffect 内での使用を検討してください。
// 悪い例 - 無限ループの可能性
{!user && <Navigate to="/login" />}
// 良い例 - useEffect 内で処理
useEffect(() => {
if (!user) {
navigate('/login', { replace: true });
}
}, [user, navigate]);
まとめ
React Router v6 でのリダイレクトは、主に以下の方法で実装します:
Navigate
コンポーネント - 宣言的なリダイレクトuseNavigate
フック - プログラム的なナビゲーション- カスタムコンポーネント - 特殊なリダイレクト要件に対応
適切な方法を選択し、ユーザーエクスペリエンスを考慮したリダイレクト実装を心がけましょう。