Authentication is an extremely common requirement for web applications. In this guide, we'll walk through how to use TanStack Router to build protected routes, and how to redirect users to login if they try to access them.
route.beforeLoad
OptionThe route.beforeLoad
option allows you to specify a function that will be called before a route is loaded. It receives all of the same arguments that the route.loader
function does. This is a great place to check if a user is authenticated, and redirect them to a login page if they are not.
The beforeLoad
function runs in relative order to these other route loading functions:
route.parseParams
route.validateSearch
route.beforeLoad
route.onError
route.component.preload?
route.loader
It's important to know that the beforeLoad
function for a route is called before any of it's child routes' beforeLoad
functions. It is essentially a middleware function for the route and all of it's children.
If you throw an error in beforeLoad
, none of its children will attempt to load.
While not required, some authentication flows require redirecting to a login page. To do this, you can throw a redirect()
from beforeLoad
:
const authenticatedRoute = new Route({ id: 'authenticated', beforeLoad: async () => { if (!isAuthenticated()) { throw redirect({ to: '/login', search: { // Use the current location to power a redirect after login // (Do not use `router.state.resolvedLocation` as it can // potentially lag behind the actual current location) redirect: router.state.location.href, }, }) } },})
ðŸ§
redirect()
takes all of the same options as thenavigate
function, so you can pass options likereplace: true
if you want to replace the current history entry instead of adding a new one.
Once you have authenticated a user, it's also common practice to redirect them back to the page they were trying to access. To do this, you can utilize the redirect
search param that we added in our original redirect. Since we'll be replacing the entire URL with what it was, router.history.push
is better suited for this than router.navigate
:
router.history.push(search.redirect)
Some applications choose to not redirect users to a login page, and instead keep the user on the same page and show a login form that either replaces the main content or hides it via a modal. This is also possible with TanStack Router by simply short circuiting rendering the <Outlet />
that would normally render the child routes:
const authenticatedRoute = new Route({ id: 'authenticated', component: () => { if (!isAuthenticated()) { return <Login /> }
return <Outlet /> },})
This keeps the user on the same page, but still allows you to render a login form. Once the user is authenticated, you can simply render the <Outlet />
and the child routes will be rendered.
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.