TanStack Router предоставляет гибкий механизм управления скроллом при навигации, что особенно важно для сложных приложений с динамическим контентом. Управление скроллом позволяет контролировать поведение страницы при переходах между маршрутами, восстанавливать позиции прокрутки и создавать пользовательский опыт, аналогичный нативным приложениям.
По умолчанию TanStack Router хранит позиции скролла для каждой
посещённой страницы. Это реализуется через объект
scrollRestoration в конфигурации роутера. Например:
import { createRouter, Route } from '@tanstack/router'
const router = createRouter({
routes: [
new Route({ path: '/', component: HomePage }),
new Route({ path: '/about', component: AboutPage }),
],
scrollRestoration: 'auto',
})
Ключевые значения для
scrollRestoration:
'auto' — браузер самостоятельно управляет позицией
скролла.'manual' — необходимо явно управлять прокруткой через
события роутера.Использование 'manual' особенно полезно для сложных
страниц с динамическим контентом, где требуется точно контролировать,
куда прокрутить пользователя после загрузки нового маршрута.
Для полного контроля над скроллом можно использовать опцию
onScrollChange. Она позволяет задавать логику прокрутки при
каждом переходе между маршрутами:
const router = createRouter({
routes,
onScrollChange: ({ from, to }) => {
if (to.path === '/about') {
window.scrollTo({ top: 0, beh * avior: 'smooth' })
} else if (from.path === '/about') {
// Сохраняем текущую позицию скролла для возврата
sessionStorage.setItem('scrollPos', window.scrollY)
}
},
})
Особенности onScrollChange:
from и to содержат информацию о
предыдущем и новом маршрутах.beh * avior: 'smooth'.sessionStorage или
localStorage для сохранения и восстановления позиций при
навигации назад и вперед.TanStack Router поддерживает асинхронное управление скроллом. Это важно, когда компонент загружается динамически или требует данных с сервера:
const router = createRouter({
routes,
onScrollChange: async ({ to }) => {
if (to.path === '/posts/:id') {
await fetchPostData(to.params.id)
const targetElement = document.getElementById('post-content')
targetElement.scrollIntoView({ beh * avior: 'smooth' })
}
},
})
Преимущества асинхронного подхода:
Для сложных приложений с табами и длинными списками часто необходимо сохранять позицию скролла при возврате на предыдущую страницу. TanStack Router позволяет реализовать это с помощью состояния маршрута:
const router = createRouter({
routes,
onScrollChange: ({ from, to }) => {
if (from) {
from.meta.scrollY = window.scrollY
}
if (to.meta.scrollY !== undefined) {
window.scrollTo({ top: to.meta.scrollY, beh * avior: 'auto' })
}
},
})
Особенности этого подхода:
meta).При работе с длинными списками или таблицами часто используется
виртуализация через react-virtual или аналогичные решения.
В этом случае стандартный window.scrollTo не работает
напрямую, и нужно управлять прокруткой контейнера виртуализированного
списка:
const router = createRouter({
routes,
onScrollChange: ({ to }) => {
const listContainer = document.getElementById('virtual-list')
if (listContainer && to.meta.scrollPos) {
listContainer.scrollTop = to.meta.scrollPos
}
},
})
Важно:
TanStack Router поддерживает вложенные маршруты, и для каждого из них можно задавать отдельную логику скролла:
const router = createRouter({
routes: [
new Route({
path: '/dashboard',
children: [
new Route({
path: 'analytics',
component: AnalyticsPage,
onScrollChange: () => window.scrollTo({ top: 100 }),
}),
new Route({
path: 'reports',
component: ReportsPage,
onScrollChange: () => window.scrollTo({ top: 0 }),
}),
],
}),
],
})
Особенности: