T
TanStack15mo ago
relaxed-coral

Implement AuthWrapper in filebased routing

How do I implemement the following code in my filebased router?
import { createReactRouter, createRouteConfig } from '@tanstack/react-router';
import { AuthWrapper } from '../components/AuthWrapper';
import Login from './login';
import Dashboard from './dashboard';
import Profile from './profile';
import AccountLocked from './account-locked';
import AccountDisabled from './account-disabled';

const rootRoute = createRouteConfig({
component: () => <Outlet />,
});

const loginRoute = rootRoute.createRoute({
path: '/login',
component: Login,
});

const accountLockedRoute = rootRoute.createRoute({
path: '/account-locked',
component: AccountLocked,
});

const accountDisabledRoute = rootRoute.createRoute({
path: '/account-disabled',
component: AccountDisabled,
});

const protectedRoutes = rootRoute.createRoute({
id: 'protected',
component: AuthWrapper,
});

const dashboardRoute = protectedRoutes.createRoute({
path: '/',
component: Dashboard,
});

const profileRoute = protectedRoutes.createRoute({
path: '/profile',
component: Profile,
});

const routeConfig = rootRoute.addChildren([
loginRoute,
accountLockedRoute,
accountDisabledRoute,
protectedRoutes.addChildren([dashboardRoute, profileRoute]),
]);

export const router = createReactRouter(routeConfig);
import { createReactRouter, createRouteConfig } from '@tanstack/react-router';
import { AuthWrapper } from '../components/AuthWrapper';
import Login from './login';
import Dashboard from './dashboard';
import Profile from './profile';
import AccountLocked from './account-locked';
import AccountDisabled from './account-disabled';

const rootRoute = createRouteConfig({
component: () => <Outlet />,
});

const loginRoute = rootRoute.createRoute({
path: '/login',
component: Login,
});

const accountLockedRoute = rootRoute.createRoute({
path: '/account-locked',
component: AccountLocked,
});

const accountDisabledRoute = rootRoute.createRoute({
path: '/account-disabled',
component: AccountDisabled,
});

const protectedRoutes = rootRoute.createRoute({
id: 'protected',
component: AuthWrapper,
});

const dashboardRoute = protectedRoutes.createRoute({
path: '/',
component: Dashboard,
});

const profileRoute = protectedRoutes.createRoute({
path: '/profile',
component: Profile,
});

const routeConfig = rootRoute.addChildren([
loginRoute,
accountLockedRoute,
accountDisabledRoute,
protectedRoutes.addChildren([dashboardRoute, profileRoute]),
]);

export const router = createReactRouter(routeConfig);
9 Replies
relaxed-coral
relaxed-coralOP15mo ago
I have the AuthWrapper setup and root route setup in my _index.jsx file whereas all the other routes like login, signup, etc are setup in their own login.jsx, signup.jsx files and etc like so, _root.jsx
import { createRootRoute, Outlet } from "@tanstack/react-router";
import { protectedRoute } from "./protected";
import Onboarding from "src/pages/Onboarding";

export const Route = createRootRoute({
component: () => (
<>
<Outlet />
</>
),
});
import { createRootRoute, Outlet } from "@tanstack/react-router";
import { protectedRoute } from "./protected";
import Onboarding from "src/pages/Onboarding";

export const Route = createRootRoute({
component: () => (
<>
<Outlet />
</>
),
});
login.jsx
import { createFileRoute } from "@tanstack/react-router";
import LogIn from "src/pages/Login";

export const Route = createFileRoute("/login")({
component: LogIn,
});
import { createFileRoute } from "@tanstack/react-router";
import LogIn from "src/pages/Login";

export const Route = createFileRoute("/login")({
component: LogIn,
});
and other sub routes are created similarly how can I implement the above code with respect to my setup? My Auth wrapper goes something like this
import { Navigate, Outlet } from "@tanstack/react-router";
import { useAuth } from "src/hooks/useAuth";

export function AuthWrapper() {
const { isAuthenticated, isLoading, user } = useAuth();

if (isLoading) {
return <div>Loading...</div>;
}

if (!isAuthenticated) {
return <Navigate to="/login" />;
}

if (user.isAccountLocked) {
return <Navigate to="/account-locked" />;
}

if (!user.isAccountEnabled) {
return <Navigate to="/account-disabled" />;
}

return <Outlet />;
}
import { Navigate, Outlet } from "@tanstack/react-router";
import { useAuth } from "src/hooks/useAuth";

export function AuthWrapper() {
const { isAuthenticated, isLoading, user } = useAuth();

if (isLoading) {
return <div>Loading...</div>;
}

if (!isAuthenticated) {
return <Navigate to="/login" />;
}

if (user.isAccountLocked) {
return <Navigate to="/account-locked" />;
}

if (!user.isAccountEnabled) {
return <Navigate to="/account-disabled" />;
}

return <Outlet />;
}
unwilling-turquoise
unwilling-turquoise15mo ago
You could achieve this with a layout route Have you looked at the authenticated routes example? Its a matter if putting your auth wrapper logic in the layout route over there.
relaxed-coral
relaxed-coralOP15mo ago
I did! But I was just wondering if there was a way without having to check for auth status and redirect on every protected route since my entire application except login and sign up pages is protected
unwilling-turquoise
unwilling-turquoise15mo ago
That's where the layout route comes in. You'll only be checking it in there. The child routes of the layout can be considered to already be authenticated.
relaxed-coral
relaxed-coralOP15mo ago
So I can have something like a _protected.jsx layout route file and use beforeLoad in that?
unwilling-turquoise
unwilling-turquoise15mo ago
Yea
relaxed-coral
relaxed-coralOP15mo ago
Currently each of my routes is setup in different files.
unwilling-turquoise
unwilling-turquoise15mo ago
Just, make them all a child of the layout route. It won't affect the URLs, so you should be fine.
relaxed-coral
relaxed-coralOP15mo ago
Okay I've implemented something based on what you've said and the docs,
// src/routes/_authenticated.tsx
import { createFileRoute, redirect } from '@tanstack/react-router';
import { store } from '../store';
import { fetchUserData } from '../api/auth';
import { setUserData } from '../store/userSlice';

export const Route = createFileRoute('/_authenticated')({
beforeLoad: async ({ location }) => {
const state = store.getState();
if (!state.user.id) {
try {
const userData = await fetchUserData();
store.dispatch(setUserData(userData));
} catch (error) {
throw redirect({
to: '/login',
search: {
redirect: location.href,
},
});
}
}
},
component: AuthenticatedLayout,
});

function AuthenticatedLayout() {
return <Outlet />;
}
// src/routes/_authenticated.tsx
import { createFileRoute, redirect } from '@tanstack/react-router';
import { store } from '../store';
import { fetchUserData } from '../api/auth';
import { setUserData } from '../store/userSlice';

export const Route = createFileRoute('/_authenticated')({
beforeLoad: async ({ location }) => {
const state = store.getState();
if (!state.user.id) {
try {
const userData = await fetchUserData();
store.dispatch(setUserData(userData));
} catch (error) {
throw redirect({
to: '/login',
search: {
redirect: location.href,
},
});
}
}
},
component: AuthenticatedLayout,
});

function AuthenticatedLayout() {
return <Outlet />;
}
This is a layout route
const routeTree = rootRoute.addChildren([
import('./login'),
import('./signup'),
import('./_authenticated'),
import('./_authenticated/dashboard'),
import('./_authenticated/profile'),
import('./_authenticated/onboarding'),
]);
const routeTree = rootRoute.addChildren([
import('./login'),
import('./signup'),
import('./_authenticated'),
import('./_authenticated/dashboard'),
import('./_authenticated/profile'),
import('./_authenticated/onboarding'),
]);

Did you find this page helpful?