Loader в TanStack Router — это функция, которая выполняется перед рендерингом компонента маршрута и отвечает за загрузку данных, необходимых для отображения страницы. Основная задача loader — предоставить компоненту готовые данные, чтобы избежать лишних состояний загрузки или повторных запросов внутри компонентов.
Loader определяется в объекте маршрута через свойство
loader. Он может быть асинхронной функцией, возвращающей
данные напрямую, либо промис, который резолвится в объект данных:
import { createRouter, createRouteConfig } from '@tanstack/router'
const route = createRouteConfig({
path: '/users/:userId',
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.userId}`);
if (!response.ok) {
throw new Error('Ошибка загрузки данных пользователя');
}
return response.json();
},
component: UserComponent,
});
В данном примере loader получает объект params, который
содержит параметры маршрута (userId), и выполняет
асинхронный запрос к API. Возвращаемые данные затем доступны компоненту
через хук useLoaderData.
Loader вызывается с объектом контекста, который содержит следующие ключи:
params — объект параметров маршрута (например,
динамические сегменты пути).search — объект с query-параметрами URL.request — объект Request, если используется TanStack
Router с поддержкой fetch API.context — общий объект контекста, который можно
передавать в router при его создании.Пример использования query-параметров:
const searchRoute = createRouteConfig({
path: '/search',
loader: async ({ search }) => {
const response = await fetch(`/api/search?q=${encodeURIComponent(search.q)}`);
return response.json();
},
component: SearchComponent,
});
Loader может выбрасывать ошибки при неудачных запросах. TanStack
Router предоставляет возможность обрабатывать такие ошибки через
ErrorBoundary, прикрепленный к маршруту:
const route = createRouteConfig({
path: '/posts/:id',
loader: async ({ params }) => {
const res = await fetch(`/api/posts/${params.id}`);
if (!res.ok) {
throw new Error('Пост не найден');
}
return res.json();
},
component: PostComponent,
errorComponent: PostErrorComponent,
});
При возникновении ошибки рендерится компонент
errorComponent, а сам компонент маршрута не
отображается.
Loader можно оптимизировать, избегая лишних запросов и повторного
рендера. TanStack Router поддерживает useLoaderData для
получения данных без повторного вызова loader при переходе по маршруту,
если данные не изменились:
import { useLoaderData } from '@tanstack/router'
function UserComponent() {
const user = useLoaderData();
return (
<div>
<h1>{user.name}</h1>
<p>Email: {user.email}</p>
</div>
);
}
Loader может одновременно запускать несколько асинхронных запросов
через Promise.all:
const dashboardRoute = createRouteConfig({
path: '/dashboard',
loader: async () => {
const [userRes, statsRes] = await Promise.all([
fetch('/api/user'),
fetch('/api/stats')
]);
const user = await userRes.json();
const stats = await statsRes.json();
return { user, stats };
},
component: DashboardComponent,
});
TanStack Router позволяет строго типизировать loader и возвращаемые данные:
type UserData = {
id: string;
name: string;
email: string;
};
const userRoute = createRouteConfig({
path: '/users/:id',
loader: async ({ params }): Promise<UserData> => {
const res = await fetch(`/api/users/${params.id}`);
return res.json();
},
component: UserComponent,
});
Использование типизации повышает предсказуемость данных и предотвращает ошибки доступа к несуществующим полям в компоненте.
useLoaderData.params, search,
request, context.errorComponent.Использование loader позволяет создавать маршруты, которые сразу предоставляют компоненту все необходимые данные, упрощают управление состоянием загрузки и делают маршрутизацию в приложении более предсказуемой и масштабируемой.