В TanStack Router управление доступом реализуется через концепцию ролей и прав доступа, что позволяет создавать гибкие схемы авторизации внутри приложений. Основная идея заключается в том, что маршруты могут быть защищены и доступны только определённым пользователям, в зависимости от их роли или состояния аутентификации.
Роли в приложении обычно представляются через объект или перечисление, которое описывает набор доступов. Например:
export const Roles = {
ADMIN: 'admin',
USER: 'user',
GUEST: 'guest',
};
Каждой роли может соответствовать набор разрешённых маршрутов. Это позволяет централизованно управлять доступом и избегать дублирования проверок по всему приложению.
TanStack Router предоставляет возможность создавать маршруты с
условием доступа. Для этого используется свойство
beforeLoad или loader, в которых можно
проверять роль пользователя.
Пример защищённого маршрута:
import { createRouter, Route } from '@tanstack/router';
import { Roles } from './roles';
import { getCurrentUser } from './auth';
const protectedRoute = new Route({
path: '/admin',
element: ,
beforeLoad: async () => {
const user = await getCurrentUser();
if (!user || user.role !== Roles.ADMIN) {
throw new Error('Доступ запрещён');
}
},
});
В этом примере проверка выполняется до загрузки компонента, что предотвращает рендеринг страницы пользователем без нужной роли.
Иногда необходимо, чтобы маршруты отображались или создавались динамически в зависимости от роли пользователя. Для этого можно использовать функцию генерации маршрутов:
function getRoutesForRole(role) {
const baseRoutes = [homeRoute, profileRoute];
if (role === Roles.ADMIN) {
return [...baseRoutes, adminRoute, manageUsersRoute];
}
if (role === Roles.USER) {
return [...baseRoutes, dashboardRoute];
}
return baseRoutes;
}
const router = createRouter({
routes: getRoutesForRole(currentUser.role),
});
Такой подход обеспечивает полное соответствие маршрутов доступным ролям без необходимости проверять права на каждом компоненте.
Иногда необходимо скрыть части интерфейса, даже если маршрут доступен пользователю. Для этого можно использовать проверку роли внутри компонента:
function AdminButton({ user }) {
if (user.role !== Roles.ADMIN) return null;
return ;
}
Это позволяет создавать контекстно-зависимый интерфейс, где элементы управления отображаются только пользователям с нужными правами.
Для удобства управления ролями TanStack Router легко интегрируется с глобальными состояниями, такими как Redux, Zustand или Context API. Например:
import { useStore } from './store';
const protectedRoute = new Route({
path: '/settings',
element: ,
beforeLoad: () => {
const user = useStore.getState().currentUser;
if (!user || user.role !== Roles.ADMIN) {
throw new Error('Доступ запрещён');
}
},
});
Использование глобального состояния упрощает доступ к информации о пользователе и роли, исключая необходимость постоянных асинхронных запросов к серверу.
Для улучшения UX можно настроить автоматические редиректы для пользователей без прав доступа:
const router = createRouter({
routes: [
{
path: '/admin',
element: ,
beforeLoad: async () => {
const user = await getCurrentUser();
if (!user || user.role !== Roles.ADMIN) {
return '/login'; // редирект на страницу входа
}
},
},
],
});
В этом случае попытка доступа к закрытому маршруту приведёт к перенаправлению на страницу авторизации или любую другую, указанную в логике.
beforeLoad или
loader маршрутов.