TanStack Router предоставляет гибкую и мощную систему управления переходами между маршрутами в приложениях на JavaScript, обеспечивая плавное и предсказуемое поведение при навигации. В основе механизма переходов лежит система хуков и событий, которые позволяют перехватывать, модифицировать или отменять переход между маршрутами.
Переход (transition) в TanStack Router — это процесс изменения текущего маршрута на другой. Он может быть синхронным или асинхронным, в зависимости от того, требуется ли предварительная загрузка данных, проверка прав доступа или выполнение анимаций.
Ключевые элементы переходов:
idle, loading,
submitting, error.Пример базового перехода с использованием
navigate():
import { useRouter } from '@tanstack/router'
const router = useRouter()
function goToProfile(userId) {
router.navigate({ to: '/profile', params: { id: userId } })
}
Одной из ключевых особенностей TanStack Router является поддержка
асинхронной загрузки данных перед переходом. Это
достигается через loader и onLoad:
const profileRoute = router.createRoute({
path: '/profile/:id',
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`)
if (!response.ok) throw new Error('Failed to load profile')
return response.json()
},
component: ProfilePage,
})
В этом примере переход на маршрут /profile/:id будет
ожидать завершения загрузки данных перед рендерингом компонента. Если
loader выбрасывает ошибку, переход автоматически переходит
в состояние error.
TanStack Router предоставляет несколько хуков для управления переходами:
Пример использования onBeforeUnload:
const editRoute = router.createRoute({
path: '/edit/:id',
onBeforeUnload: ({ next }) => {
if (unsavedChangesExist()) {
return confirm('У вас есть несохраненные изменения. Продолжить?')
? true
: false
}
return true
},
component: EditPage,
})
Если пользователь попытается покинуть маршрут с несохраненными изменениями, переход может быть остановлен или подтвержден.
Для визуальных эффектов TanStack Router не содержит встроенной системы анимаций, но позволяет интегрировать сторонние библиотеки (например, Framer Motion или React Transition Group) через transitionState:
import { useTransition, useRouter } from '@tanstack/router'
const router = useRouter()
const transition = useTransition()
return (
<div>
{transition.state === 'loading' && <LoadingSpinner />}
<AnimatedRoutes key={router.currentRoute.id}>
<RouterView />
</AnimatedRoutes>
</div>
)
Состояние transition.state позволяет управлять
отображением спиннеров или запуском анимаций при начале перехода и
завершении загрузки маршрута.
Иногда необходимо временно заблокировать переход, например, при
асинхронной валидации или сохранении формы. Для этого используется
объект transition с методами pause() и
resume():
router.addTransitionHook(async (transition) => {
if (needsValidation()) {
transition.pause()
await validateData()
transition.resume()
}
})
Такой подход обеспечивает точный контроль над тем, когда переход продолжается, предотвращая потерю данных или некорректное состояние приложения.
TanStack Router предоставляет централизованную обработку ошибок через
errorBoundary на уровне маршрута или глобально:
const dashboardRoute = router.createRoute({
path: '/dashboard',
loader: async () => {
throw new Error('Failed to load dashboard')
},
errorBoundary: ({ error }) => <ErrorComponent message={error.message} />,
component: DashboardPage,
})
Любая ошибка в loader, onEnter или других
хуках автоматически попадает в errorBoundary, позволяя
корректно отобразить состояние ошибки, не ломая приложение.
Маршруты могут быть связаны между собой через динамические параметры и nested routes, что позволяет создавать цепочки переходов:
const userRoute = router.createRoute({
path: '/users/:userId',
children: [
{
path: 'settings',
component: UserSettingsPage,
},
{
path: 'posts',
component: UserPostsPage,
},
],
})
При переходе из /users/1 в /users/1/posts
TanStack Router автоматически определяет общий родительский
маршрут, выполняет onExit и onEnter
только для затронутых маршрутов, минимизируя лишние перерендеры.
TanStack Router поддерживает интерактивное управление переходом, что особенно полезно для сложных приложений:
router.navigate().loader и проверок.transition.state = 'loading'.onExit старого маршрута и onEnter
нового.Этот пошаговый механизм делает маршрутизацию предсказуемой и безопасной, позволяя интегрировать анимации, блокировки и обработку ошибок без конфликтов.
Механизм переходов в TanStack Router сочетает гибкость и контроль. Он объединяет асинхронные загрузки данных, хуки для входа и выхода с маршрутов, блокировку переходов, обработку ошибок и возможность интеграции анимаций. Такой подход делает маршрутизацию мощным инструментом для построения сложных веб-приложений, где точное управление навигацией критично для пользовательского опыта.