TanStack Router предоставляет мощные возможности для управления навигацией и состоянием приложения, что особенно важно при работе с современными SPA. Одним из ключевых аспектов является согласование состояния роутера с глобальным или локальным store, что позволяет поддерживать синхронное состояние URL и внутренние данные приложения.
В TanStack Router состояние роутера включает в себя:
pathname) – строка,
отображающая текущий URL.params) – объект с
динамическими сегментами URL.search) – объект с
параметрами запроса.state) – объект, передаваемый
через навигацию, аналог history.state в браузере.Эти элементы состояния могут использоваться напрямую для синхронизации с хранилищами данных. Важно понимать, что роутер не хранит бизнес-логику, он лишь отражает состояние маршрутизации. Все остальные данные (например, выбранный элемент в списке, фильтры, настройки отображения) должны быть согласованы через store.
Для интеграции TanStack Router с глобальными store, например, Redux, Zustand или Jotai, следует соблюдать несколько принципов:
Инициализация состояния из URL При загрузке
страницы store должен получать значения, закодированные в URL. Например,
текущий фильтр таблицы или сортировка могут быть извлечены из
search:
const currentFilters = parseSearch(router.state.search);
store.setFilters(currentFilters);Синхронизация store с изменением маршрута
Использование хука useRouter или подписка на события
роутера позволяет реагировать на изменения URL:
useEffect(() => {
const unsubscribe = router.subscribe(({ search, params }) => {
store.setFilters(parseSearch(search));
store.setItemId(params.id);
});
return unsubscribe;
}, [router]);Обновление URL при изменении store Когда данные в store меняются, важно обновлять URL, чтобы пользователь мог делиться ссылкой с актуальным состоянием:
useEffect(() => {
const search = serializeFilters(store.filters);
router.navigate({ search });
}, [store.filters]);TanStack Router поддерживает вложенные маршруты, где каждый уровень маршрута может иметь собственное состояние. Для таких случаев рекомендуется:
Хранить локальное состояние в дочерних store или атомах, привязанных к конкретному роуту.
Использовать route.id или route.path
как ключ для синхронизации состояния:
const routeKey = router.state.currentRoute.id;
const localState = localStore.getState(routeKey);Поддерживать обратную синхронизацию, чтобы изменения локального состояния отражались в URL и обратно:
useEffect(() => {
const search = serializeLocalState(localState);
router.navigate({ search }, { replace: true });
}, [localState]);TanStack Router предоставляет хуки loader и
onLoadError для асинхронной загрузки данных, которые можно
интегрировать с store:
Loader: используется для предзагрузки данных перед отображением маршрута. Полученные данные можно сохранять в store:
const userLoader = async ({ params }) => {
const user = await api.fetchUser(params.userId);
store.setUser(user);
return user;
};Обработка ошибок и fallback: синхронизация store с ошибкой позволяет управлять состоянием приложения без нарушения маршрута:
const onEr ror = (error) => {
store.setError(error.message);
};Для компонентов, таких как таблицы с фильтрацией и пагинацией, TanStack Router совместно с store позволяет:
Сохранять текущие фильтры в URL, чтобы обеспечить возможность закладки и обмена ссылкой.
Поддерживать согласованную сортировку и страницу при навигации между маршрутами.
Обновлять store при изменении URL и наоборот, избегая бесконечных циклов через проверку актуальности значений:
if (!isEqual(router.state.search, serializeFilters(store.filters))) {
router.navigate({ search: serializeFilters(store.filters) });
}Основной паттерн интеграции роутера и store — двусторонняя синхронизация:
router.navigate.Эта схема обеспечивает:
Такой подход делает TanStack Router эффективным инструментом для построения больших, динамичных SPA, где состояние маршрута и данные приложения находятся в постоянной синхронизации.