Vite + TanStack Router - 6. 認証付きルートの設定
外部の認証サービスを使っている場合、useAuth() などのフックを使ってユーザーのログイン状態を取得することになりますが、フックはコンポーネント内でしか使えないため、 createFileRouteのbeforeLoad では呼び出せません。
そのため、あらかじめ認証状態を取得し、RouterContextを使って各ルートに伝えるようにします。
手順としては以下のようになります。
RootRouteをContext付きで作成<App />コンポーネントで認証状態を取得し、Contextにセット- 各ページで
contextを参照し、認証状態を確認
1. RootRouteをContext付きで作成
src/routes/__root.tsxファイルでルーターを初期化する際に、createRootRouteではなく、createRootRouteWithContext を使います。
この例ではAuth0を例としてあげています、Auth0の部分はご利用のSaaSに置き換えてください。
import { createRootRouteWithContext, Outlet } from "@tanstack/react-router";import { useAuth0 } from '@auth0/auth0-react';
//...
type RouterContext = { auth: ReturnType<typeof useAuth0>; };
export const Route = createRootRouteWithContext<RouterContext>()({ component: () => <Outlet />, // 省略可 });
//...注意点として createRootRouteWithContextは2回呼ぶ必要があります。
createRootRoute() // ()1回createRootRouteWithContext<T>()() // ()2回2. <App /> コンポーネントで認証状態を取得し、contextにセット
App.tsx で useAuth0を呼び出して認証状態を取得し、RouterContext にセットします。
import { RouterProvider, createRouter } from "@tanstack/react-router";import { useAuth0 } from '@auth0/auth0-react';import { routeTree } from "./routeTree.gen";import "./App.css";
const router = createRouter({ routeTree, context: { auth: undefined!, },});
declare module "@tanstack/react-router" { interface Register { router: typeof router; }}
function App() { const auth = useAuth0(); return ( <> <RouterProvider router={router} context={{auth}} /> </> );}
export default App;3. 各ページでcontext を参照し、認証状態を確認
adminページで beforeLoadで認証状態をContextから読み出し、ログインしていなければredirect()をスローしてログイン画面に遷移します。
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/admin')({ beforeLoad: ({ context, location }) => { if (!context.auth.isAuthenticated) { throw redirect({ to: '/login', search: { redirect: location.href, }, }) } },})まとめ
beforeLoadでフックは使えないので、認証状態はContextに入れておく必要がある- Contextを使うには
createRootRouteWithContextでルートを作る createRootRouteWithContextは高階関数なので戻り値を再度呼ぶ必要がる