loader в TanStack Router отвечает за асинхронное
получение данных до того, как страница или компонент будут отображены.
Понимание работы и возможностей отладки loader-ов
критически важно для построения надежных маршрутов и корректного
управления состоянием приложения.
loaderКаждый маршрут может содержать функцию loader, которая
вызывается при навигации к этому маршруту. Функция получает объект с
параметрами маршрута, объект запроса и контекст, и должна возвращать
данные, необходимые для рендера компонента.
Пример базового loader:
const userLoader = async ({ params }) => {
const response = await fetch(`/api/users/${params.userId}`);
if (!response.ok) {
throw new Response('User not found', { status: 404 });
}
return response.json();
};
Ключевые моменты:
params содержит динамические параметры URL
(:userId в примере).loader могут быть обработаны через
маршруты ошибок (errorElement) или глобальные обработчики
ошибок.useLoaderData().Для диагностики проблем с loader-ами удобно
использовать:
const productLoader = async ({ params }) => {
console.log('Params:', params);
return fetch(`/api/products/${params.productId}`).then(res => res.json());
};
const loaderWithErrorHandling = async ({ params }) => {
try {
const response = await fetch(`/api/items/${params.id}`);
if (!response.ok) throw new Error('Item not found');
return response.json();
} catch (error) {
console.error('Loader error:', error);
throw error;
}
};
debugger:Прямое добавление debugger; внутри loader
позволяет остановить выполнение и пошагово проверить значения
параметров, ответ сервера и логику обработки ошибок.
ErrorBoundary и errorElementTanStack Router позволяет задать компонент для отображения ошибок маршрута:
const ErrorComponent = ({ error }) => (
<div>
<h2>Ошибка загрузки данных</h2>
<pre>{error.message}</pre>
</div>
);
const route = {
path: '/users/:userId',
loader: userLoader,
errorElement: <ErrorComponent />,
};
Особенности:
loader автоматически передаются компоненту
errorElement.useLoaderData().loader-ами, и их ответы.loader: можно
тестировать асинхронные функции отдельно, подставляя мокированные
params и ответы сервера:test('loader fetches user data', async () => {
global.fetch = jest.fn(() =>
Promise.resolve({ ok: true, json: () => ({ name: 'John' }) })
);
const data = await userLoader({ params: { userId: '1' } });
expect(data.name).toBe('John');
});
loader и useLoaderData(). Проверка того,
обновляются ли данные после навигации, помогает выявить ошибки
кэширования.isLoading и pending позволяет отслеживать
момент начала и окончания загрузки данных.loader-ах важно логировать каждый шаг цепочки и
обрабатывать ошибки на каждом уровне.AbortController для предотвращения утечек данных при
быстром переключении маршрутов.const cancellableLoader = async ({ params, signal }) => {
const controller = new AbortController();
signal.addEventListener('abort', () => controller.abort());
const response = await fetch(`/api/data/${params.id}`, { signal: controller.signal });
return response.json();
};
loader-овdebugger для пошагового анализа.errorElement для визуализации проблем.loader.Такая комплексная практика позволяет выявлять большинство проблем с загрузкой данных на раннем этапе и обеспечивает стабильность приложения при масштабировании маршрутов и компонентов.