Skip to main content

<ProtectedRoute />

The ProtectedRoute component wraps a route component and enforces authentication. When the user is not signed in it either redirects to a specified URL or renders a fallback element. While authentication state is being resolved it shows a loading state.

note

ProtectedRoute must be rendered inside a ThunderIDProvider. It also requires TanStack Router's router context: wrap your application with RouterProvider.

Usage​

Basic Usage​

Use ProtectedRoute in the component of a TanStack Router route definition:

src/routes.tsx
import { createRoute } from '@tanstack/react-router'
import { ProtectedRoute } from '@thunderid/tanstack-router'
import Dashboard from './pages/Dashboard'

export const dashboardRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => (
<ProtectedRoute redirectTo="/signin">
<Dashboard />
</ProtectedRoute>
),
})

Custom Fallback​

Render a custom element instead of redirecting when the user is not authenticated:

src/routes.tsx
createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => (
<ProtectedRoute
fallback={
<div>
<h2>Sign in required</h2>
<p>You must be signed in to view this page.</p>
</div>
}
>
<Dashboard />
</ProtectedRoute>
),
})

Custom Loading State​

Replace the default null loading state with a spinner or skeleton:

src/routes.tsx
createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => (
<ProtectedRoute
redirectTo="/signin"
loader={<div className="spinner">Loading...</div>}
>
<Dashboard />
</ProtectedRoute>
),
})

Protecting a Nested Layout​

Protect a group of routes by placing ProtectedRoute in a shared layout route:

src/routes.tsx
import { createRoute, Outlet } from '@tanstack/react-router'
import { ProtectedRoute } from '@thunderid/tanstack-router'

const appLayoutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/app',
component: () => (
<ProtectedRoute redirectTo="/signin">
<Outlet />
</ProtectedRoute>
),
})

const dashboardRoute = createRoute({
getParentRoute: () => appLayoutRoute,
path: '/dashboard',
component: Dashboard,
})

const settingsRoute = createRoute({
getParentRoute: () => appLayoutRoute,
path: '/settings',
component: Settings,
})

Props​

PropTypeRequiredDescription
childrenReactElement✅The element to render when the user is authenticated
redirectTostring❌Path to redirect unauthenticated users to. Either redirectTo or fallback must be provided
fallbackReactElement❌Element to render when the user is not authenticated. Either redirectTo or fallback must be provided
loaderReactNode❌Element to render while authentication state is being resolved. Defaults to null
note

You must provide either redirectTo or fallback. If neither is provided, a ThunderIDRuntimeError is thrown.

Differences from @thunderid/react-router​

The TanStack Router ProtectedRoute does not include onSignIn or signInOptions props. For custom sign-in logic, use the useThunderID() hook directly in the protected component or layout.

Error Handling​

ProtectedRoute throws a ThunderIDRuntimeError if neither redirectTo nor fallback is provided.

// This will throw — one of redirectTo or fallback is required
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.