TanStack Router предоставляет гибкие механизмы управления переходами между маршрутами, включая возможность перехвата действий пользователя и запроса подтверждения при уходе со страницы. Это особенно важно для форм и других интерактивных интерфейсов, где потеря несохранённых данных может привести к ошибкам или неудобствам.
exitGuard для контроля уходаОсновным инструментом для реализации подтверждения ухода со страницы
является функция exitGuard. Она позволяет задать проверку
перед сменой маршрута. Если проверка возвращает false или
промис, который отклоняется, переход будет отменён.
Пример базовой конфигурации:
import { createRouter, Route } from '@tanstack/router';
const router = createRouter({
routeTree: rootRoute,
});
const formRoute = new Route({
path: '/form',
component: FormComponent,
exitGuard: (route, next) => {
if (route.meta.isFormDirty) {
return window.confirm('У вас есть несохранённые изменения. Вы уверены, что хотите уйти?');
}
return true;
},
});
В этом примере:
exitGuard вызывается при попытке уйти с текущего
маршрута.route.meta.isFormDirty.window.confirm.true разрешает переход, false его
блокирует.TanStack Router поддерживает асинхронные проверки, что удобно при необходимости взаимодействовать с сервером или локальными хранилищами перед уходом.
exitGuard: async (route, next) => {
if (route.meta.isFormDirty) {
const shouldLeave = await fetch('/api/check-unsaved', {
method: 'POST',
body: JSON.stringify({ formId: route.meta.formId }),
}).then(res => res.json());
return shouldLeave.confirmed;
}
return true;
}
Особенности:
exitGuard может возвращать промис.Помимо локальных exitGuard на уровне маршрута, можно
использовать глобальные перехватчики на уровне роутера. Это полезно для
реализации единой логики защиты всех маршрутов, содержащих формы или
важные данные.
router.addExitGuard(async (route, next) => {
if (route.meta.isFormDirty) {
return window.confirm('Есть несохранённые изменения. Продолжить?');
}
return true;
});
Особенности глобальных перехватчиков:
exitGuard.Для корректной работы подтверждений ухода важно хранить флаг “грязной
формы” в состоянии маршрута. TanStack Router позволяет использовать
объект meta маршрута для этих целей:
const formRoute = new Route({
path: '/form',
component: FormComponent,
meta: {
isFormDirty: false,
},
});
При изменении формы:
function handleInputChange() {
formRoute.meta.isFormDirty = true;
}
Преимущества такого подхода:
window.confirm блокирует выполнение до
пользовательского решения, поэтому рекомендуется использовать кастомные
модальные окна для улучшения пользовательского опыта.exitGuard могут замедлять переходы, если
длительное взаимодействие с сервером.meta корректно обновлялось при возврате на предыдущие
страницы.В React компонентах можно использовать useEffect для
обновления состояния маршрута при изменении формы:
import { useEffect } from 'react';
import { useRoute } from '@tanstack/router';
function FormComponent() {
const route = useRoute();
useEffect(() => {
const handleChange = () => {
route.meta.isFormDirty = true;
};
document.querySelector('form').addEventListener('input', handleChange);
return () => {
document.querySelector('form').removeEventListener('input', handleChange);
};
}, [route]);
return ;
}
Преимущества:
exitGuard.TanStack Router позволяет комбинировать exitGuard с
хуками beforeLoad и afterLoad, что открывает
возможности для более сложной логики, например, сохранения данных на
сервере при уходе:
beforeLoad: async (route) => {
if (route.meta.isFormDirty) {
await saveFormData(route.meta.formData);
}
}
Эта комбинация делает роутинг не просто навигацией, а полноценным инструментом управления состоянием приложения.