TanStack Router предлагает мощные возможности для организации маршрутизации в приложениях на JavaScript и TypeScript, особенно когда речь идет о строгой типизации контекста. Контекст маршрута — это объект, который передается каждому маршруту и содержит данные, которые могут быть использованы компонентами внутри этого маршрута. Правильная типизация контекста повышает безопасность кода и снижает вероятность ошибок на этапе компиляции.
Контекст в TanStack Router создается с помощью generic-параметров маршрута. Каждый маршрут может иметь собственный тип контекста, который затем доступен в обработчиках и компонентах маршрута.
import { createRouter, createRoute } from '@tanstack/router';
type UserContext = {
userId: string;
isAdmin: boolean;
};
const userRoute = createRoute({
path: '/user/:userId',
context: {} as UserContext,
});
В данном примере UserContext описывает данные, которые
будут доступны маршруту /user/:userId. Объявление через
context: {} as UserContext гарантирует, что любые обращения
к контексту маршрута будут строго соответствовать типу
UserContext.
Контекст становится доступным в функциях загрузки данных
(loader) и в компонентах, привязанных к маршруту. TanStack
Router обеспечивает строгую типизацию этих функций через
generic-параметры маршрута.
const userRoute = createRoute({
path: '/user/:userId',
context: {} as UserContext,
loader: async ({ context }) => {
// context.userId и context.isAdmin доступны и строго типизированы
const response = await fetch(`/api/users/${context.userId}`);
return response.json();
},
});
Здесь context автоматически имеет тип
UserContext. Ошибки обращения к несуществующим полям будут
выявлены TypeScript на этапе компиляции, что предотвращает потенциальные
runtime-ошибки.
Маршруты могут быть вложенными, и контексты могут наследоваться и комбинироваться. TanStack Router позволяет определять базовый контекст на родительском маршруте, который будет расширяться дочерними маршрутами.
type AppContext = {
sessionId: string;
};
type DashboardContext = AppContext & {
dashboardId: string;
};
const appRoute = createRoute({
path: '/',
context: {} as AppContext,
});
const dashboardRoute = createRoute({
path: '/dashboard/:dashboardId',
parent: appRoute,
context: {} as DashboardContext,
});
В этом примере дочерний маршрут dashboardRoute наследует
поля родительского контекста и добавляет собственное поле
dashboardId. Любая попытка использовать контекст без учёта
этих полей будет отмечена TypeScript как ошибка.
TanStack Router поддерживает объединение типизации URL-параметров и контекста. Это позволяет полностью типизировать все данные маршрута, включая динамические сегменты URL.
type UserParams = { userId: string };
type UserContext = { isAdmin: boolean };
const userRoute = createRoute({
path: '/user/:userId',
params: {} as UserParams,
context: {} as UserContext,
});
const loader = async ({ params, context }: { params: UserParams; context: UserContext }) => {
if (context.isAdmin) {
return fetch(`/api/admin/users/${params.userId}`).then(res => res.json());
}
return fetch(`/api/users/${params.userId}`).then(res => res.json());
};
Параметры params и контекст context строго
типизированы, что позволяет безопасно использовать их внутри асинхронных
загрузчиков данных.
При использовании TanStack Router с React контекст маршрута
автоматически становится доступным через хук
useRouteContext. Типизация контекста обеспечивает
автодополнение и проверку типов внутри компонентов.
import { useRouteContext } from '@tanstack/router';
function UserProfile() {
const { userId, isAdmin } = useRouteContext<UserContext>();
return (
<div>
<p>User ID: {userId}</p>
<p>Admin Access: {isAdmin ? 'Yes' : 'No'}</p>
</div>
);
}
Компилятор TypeScript проверяет, что userId и
isAdmin существуют в контексте и имеют правильные типы.
Попытка обратиться к несуществующему полю приведет к ошибке на этапе
разработки.
useRouteContext
только с правильно типизированными контекстами, чтобы избежать ошибок
при извлечении данных внутри компонентов.TanStack Router с его системой типизации контекста обеспечивает строгую проверку данных маршрутов на этапе компиляции. Это снижает вероятность ошибок, упрощает сопровождение приложения и делает работу с маршрутизацией безопасной и предсказуемой.