useLoaderData — это хук, предназначенный для работы с
асинхронными данными, загружаемыми через маршруты TanStack Router. Он
позволяет компонентам получать данные, определённые в
loader маршрута, без необходимости вручную управлять
состоянием загрузки или обработкой ошибок.
Каждый маршрут в TanStack Router может иметь функцию
loader. Она вызывается при переходе на маршрут и возвращает
данные, которые будут доступны через useLoaderData.
Сигнатура loader выглядит следующим образом:
const route = {
path: "/posts/:postId",
loader: async ({ params, context }) => {
const response = await fetch(`https://api.example.com/posts/${params.postId}`);
if (!response.ok) {
throw new Response("Ошибка загрузки поста", { status: response.status });
}
return response.json();
}
};
Ключевые моменты:
params — объект с параметрами маршрута, например
postId.context — глобальный объект контекста, передаваемый
маршрутизатору.loader может выбрасывать ошибки через
throw new Response(), которые будут обработаны механизмами
TanStack Router для ошибок.useLoaderDataПосле определения loader данные доступны внутри
компонента через хук useLoaderData:
import { useLoaderData } from "@tanstack/router";
function PostPage() {
const post = useLoaderData();
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
}
Особенности работы хука:
useLoaderData автоматически подписывается на данные
маршрута. Если при навигации данные обновятся, компонент перерендерится
с новыми значениями.loader.TanStack Router сам обрабатывает асинхронность loader и
предоставляет удобные механизмы для управления состоянием загрузки и
ошибок. При необходимости можно использовать хуки
useNavigation и useIsFetching для контроля
процесса загрузки:
import { useNavigation, useIsFetching } from "@tanstack/router";
function PostPage() {
const post = useLoaderData();
const navigation = useNavigation();
const isFetching = useIsFetching();
if (navigation.state === "loading" || isFetching) {
return <p>Загрузка данных...</p>;
}
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
}
Важно: useLoaderData не блокирует
рендеринг; компонент может отображаться до того, как данные будут
загружены, если используется серверная отрисовка или Suspense.
useLoaderData возвращает данные, зависящие от текущих
параметров маршрута. Это позволяет динамически подгружать ресурсы:
const route = {
path: "/users/:userId",
loader: async ({ params }) => {
return fetch(`https://api.example.com/users/${params.userId}`).then(res => res.json());
}
};
function UserPage() {
const user = useLoaderData();
return <h2>{user.name}</h2>;
}
Если пользователь переходит с одного userId на другой,
TanStack Router повторно вызовет loader и обновит данные, а
useLoaderData автоматически вернёт новый результат.
При использовании TypeScript можно указать тип возвращаемого
loader и тем самым получить типизированный результат в
useLoaderData:
interface Post {
id: number;
title: string;
body: string;
}
const postRoute = {
path: "/posts/:postId",
loader: async ({ params }): Promise<Post> => {
const res = await fetch(`/api/posts/${params.postId}`);
return res.json();
}
};
function PostPage() {
const post = useLoaderData<Post>();
return <h1>{post.title}</h1>;
}
Такой подход предотвращает ошибки при обращении к полям объекта и улучшает автодополнение в редакторе кода.
Если loader выбрасывает исключение, TanStack Router
позволяет перехватить его через специальный маршрут с
errorElement:
const postRoute = {
path: "/posts/:postId",
loader: async ({ params }) => {
const res = await fetch(`/api/posts/${params.postId}`);
if (!res.ok) throw new Response("Пост не найден", { status: 404 });
return res.json();
},
errorElement: <p>Не удалось загрузить пост.</p>
};
useLoaderData в этом случае не вернёт данные, а
компонент с errorElement будет отрисован автоматически.
TanStack Router поддерживает кэширование данных loader
на уровне маршрута. При возврате на уже посещённый маршрут, если
параметры не изменились, useLoaderData вернёт
закэшированные данные без повторного запроса, что повышает
производительность и снижает нагрузку на сервер.
useLoaderData может быть интегрирован с React Suspense
для отображения индикатора загрузки на уровне компонентов:
<Suspense fallback={<p>Загрузка...</p>}>
<PostPage />
</Suspense>
При этом TanStack Router подождёт завершения loader
перед рендером содержимого, что позволяет создавать гладкие
пользовательские интерфейсы без промежуточных пустых состояний.
Эта структура использования useLoaderData делает
TanStack Router мощным инструментом для построения маршрутов с
асинхронными данными, обеспечивая строгую типизацию, эффективное
кэширование и удобное управление состоянием загрузки и ошибок.