TanStack Router предоставляет мощный механизм управления асинхронными данными и повторными запросами в маршрутизируемых приложениях. Основная цель — обеспечить синхронизацию состояния маршрутов с серверными данными без лишних перезагрузок и избыточных запросов.
Каждый маршрут может определять loader — функцию,
возвращающую данные, необходимые компоненту для рендеринга. Loader
вызывается при первом переходе на маршрут и при необходимости обновления
данных. Пример определения loader:
import { createRouter, createRoute } from '@tanstack/router'
const userRoute = createRoute({
path: '/user/:id',
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`)
if (!response.ok) throw new Error('Ошибка загрузки пользователя')
return response.json()
}
})
Важная особенность: loader вызывается автоматически при изменении
параметров маршрута (params) или при вызове методов
повторного запроса.
useLoaderДля получения данных внутри компонента используется хук
useLoader:
import { useLoader } from '@tanstack/router'
function UserPage() {
const { data, reload, isLoading, error } = useLoader(userRoute.loader)
if (isLoading) return Загрузка...
if (error) return Ошибка: {error.message}
return (
{data.name}
)
}
Ключевые моменты:
reload() инициирует повторный вызов loader, позволяя
обновить данные без изменения маршрута.isLoading указывает на состояние ожидания ответа.error содержит объект ошибки при неудачном
запросе.TanStack Router поддерживает стратегию автоматического обновления данных при изменении контекста маршрута:
Пример использования кэширования с автообновлением:
const userRoute = createRoute({
path: '/user/:id',
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`)
return response.json()
},
// Тайм-аут кэша: 30 секунд
cacheTime: 30000
})
Для более динамичных приложений можно использовать подписки на
изменения состояния или внешние события. TanStack Router позволяет
интегрировать подписки с loader через invalidate:
import { router } from './router'
function onUserUpdated(userId) {
router.invalidate(userRoute.path, { params: { id: userId } })
}
Метод invalidate инициирует повторный вызов loader и
обновление данных на всех компонентах, использующих этот маршрут. Это
особенно полезно для реактивного обновления UI после изменения данных на
сервере.
TanStack Router предоставляет гибкость в управлении повторными запросами:
reload) —
вызов loader независимо от кэша.invalidate) —
обновление данных с проверкой, какие маршруты зависят от устаревших
данных.refetchOnMount) — опция, позволяющая loader
автоматически обновлять данные при монтировании компонента.Пример настройки автоматического обновления:
const postsRoute = createRoute({
path: '/posts',
loader: fetchPosts,
options: {
refetchOnMount: true
}
})
Loader может быть обернут в логику повторных попыток при временных сбоях сервера:
async function fetchWithRetry(url, retries = 3) {
for (let attempt = 0; attempt < retries; attempt++) {
try {
const response = await fetch(url)
if (!response.ok) throw new Error('Ошибка сети')
return await response.json()
} catch (error) {
if (attempt === retries - 1) throw error
}
}
}
Такой подход совместим с loader TanStack Router, обеспечивая надёжное получение данных даже при нестабильном соединении.
При сложных маршрутах, требующих несколько асинхронных запросов,
рекомендуется использовать Promise.all внутри loader:
const dashboardRoute = createRoute({
path: '/dashboard',
loader: async () => {
const [stats, notifications] = await Promise.all([
fetch('/api/stats').then(res => res.json()),
fetch('/api/notifications').then(res => res.json())
])
return { stats, notifications }
}
})
Это позволяет минимизировать время ожидания и оптимизировать загрузку компонентов с множеством зависимостей данных.