14. Router: loaders и данные
Что такое лоадеры?
Заголовок раздела «Что такое лоадеры?»Лоадеры — функции, которые загружают данные до рендеринга компонента маршрута. Это ключевое
отличие от useQuery внутри компонента: данные готовы к моменту первого рендеринга.
export const Route = createFileRoute('/users/$userId')({ loader: async ({ params }) => { const user = await fetchUser(params.userId) return user // Данные доступны через Route.useLoaderData() }, component: UserDetail,})Доступ к данным лоадера
Заголовок раздела «Доступ к данным лоадера»function UserDetail() { const user = Route.useLoaderData() // user: User — полностью типизировано, никогда не undefined return <h1>{user.name}</h1>}Интеграция с TanStack Query
Заголовок раздела «Интеграция с TanStack Query»Лучшая практика — использовать queryClient.ensureQueryData в лоадере:
export const Route = createFileRoute('/users/$userId')({ loader: ({ context: { queryClient }, params }) => queryClient.ensureQueryData({ queryKey: ['user', params.userId], queryFn: () => fetchUser(params.userId), }), component: UserDetail,})
function UserDetail() { // Данные уже в кэше Query — useQuery вернёт их мгновенно const { data: user } = useQuery({ queryKey: ['user', Route.useParams().userId], queryFn: () => fetchUser(Route.useParams().userId), })}beforeLoad
Заголовок раздела «beforeLoad»beforeLoad выполняется до лоадера. Используется для проверки авторизации, редиректов:
export const Route = createFileRoute('/dashboard')({ beforeLoad: ({ context }) => { if (!context.auth.isAuthenticated) { throw redirect({ to: '/login' }) } }, loader: () => fetchDashboardData(),})Параллельная загрузка
Заголовок раздела «Параллельная загрузка»По умолчанию лоадеры вложенных маршрутов выполняются параллельно:
/users → loader: fetchUsers() ─┐ /$userId → loader: fetchUser(id) ─┤ Параллельно! /posts → loader: fetchUserPosts() ─┘Чтобы дождаться родительского лоадера:
loader: async ({ params, context }) => { const user = await context.loaderData // Данные родительского лоадера return fetchPostsForUser(user.id)}Error и Pending компоненты
Заголовок раздела «Error и Pending компоненты»export const Route = createFileRoute('/users')({ loader: getUsers, pendingComponent: () => <Spinner />, errorComponent: ({ error }) => <ErrorMessage error={error} />, component: UsersList,})staleTime для лоадеров
Заголовок раздела «staleTime для лоадеров»Контроль как часто перезагружаются данные лоадера:
export const Route = createFileRoute('/users')({ loader: getUsers, staleTime: 1000 * 60, // Данные актуальны 1 минуту})