Vite + TanStack Router - 6. 認証付きルートの設定

[vite]

[TanStack]

[TanStack Router]

外部の認証サービスを使っている場合、useAuth() などのフックを使ってユーザーのログイン状態を取得することになりますが、フックはコンポーネント内でしか使えないため、 createFileRoutebeforeLoad では呼び出せません。

そのため、あらかじめ認証状態を取得し、RouterContextを使って各ルートに伝えるようにします。

手順としては以下のようになります。

  1. RootRouteをContext付きで作成
  2. <App /> コンポーネントで認証状態を取得し、Contextにセット
  3. 各コンポーネントで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.tsxuseAuth0を呼び出して認証状態を取得し、RouterContext にセットします。

import { RouterProvider, createRouter } from "@tanstack/react-router";
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() {
return (
<>
<RouterProvider router={router} context={{auth}} />
</>
);
}
export default App;

3. 各コンポーネントでcontext を参照し、認証状態を確認

コンポーネントでは 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,
},
})
}
},
})

まとめ

Vite + TanStack Router - 5. 遅延ローディングのためのコード分割