Блокировка навигации — это механизм, позволяющий контролировать переходы между маршрутами, предотвращать потерю несохранённых данных и реализовывать условную маршрутизацию. В TanStack Router этот процесс гибко настраивается через хуки жизненного цикла маршрутов и функции-guards. Рассмотрим их подробности.
beforeUnload и block для глобальной
блокировкиTanStack Router позволяет перехватывать попытки навигации с помощью
функции block. Этот метод возвращает колбэк, который
вызывается каждый раз, когда пользователь или приложение пытается
перейти на другой маршрут. Основной синтаксис:
import { router } from './router';
const unblock = router.block((tx) => {
if (!confirm('У вас есть несохранённые изменения. Выйти?')) {
return false; // блокировка перехода
}
tx.retry(); // разрешение перехода
});
tx — объект транзакции перехода,
содержащий метод retry(), который позволяет повторить
переход после принятия решения.false из колбэка полностью
блокирует навигацию.unblock().Такой подход полезен для реализации предупреждений о несохранённых данных на уровне всего приложения.
Для контроля переходов внутри конкретного маршрута TanStack Router
предоставляет опцию beforeExit. Она подключается к объекту
маршрута и вызывается перед уходом со страницы:
const profileRoute = {
path: '/profile',
component: ProfilePage,
beforeExit: ({ router, next }) => {
if (unsavedChanges()) {
if (!confirm('Сохранить изменения перед выходом?')) {
return false; // блокировка перехода
}
}
next(); // разрешение перехода
}
};
next() — продолжение навигации после
проверки.TanStack Router поддерживает асинхронные guards, что удобно для сложной логики. Например:
const settingsRoute = {
path: '/settings',
component: SettingsPage,
beforeExit: async ({ next }) => {
const shouldExit = await showSaveDialog();
if (!shouldExit) return false; // блокировка перехода
next();
}
};
beforeExit может возвращать
Promise или void.beforeExit и глобального blockДля сложных приложений часто используют оба метода одновременно:
router.block((tx) => {
if (unsavedGlobalChanges()) {
if (!confirm('Вы уверены, что хотите покинуть сайт?')) {
return false;
}
}
tx.retry();
});
block ухудшает UX.next() или возвращать false для предсказуемого
поведения.unblock() обязательна при размонтировании компонентов,
чтобы предотвратить утечки памяти.import { createRouter } from '@tanstack/router';
const router = createRouter({
routes: [
{
path: '/edit',
component: EditPage,
beforeExit: async ({ next }) => {
if (hasUnsavedChanges()) {
const confirmExit = await showExitConfirmation();
if (!confirmExit) return false;
}
next();
}
},
{ path: '/', component: HomePage }
]
});
// Глобальная блокировка для всех маршрутов
const unblock = router.block((tx) => {
if (globalUnsavedChanges()) {
if (!confirm('Сохранить изменения перед уходом?')) return false;
}
tx.retry();
});
Этот пример демонстрирует полное сочетание локальных и глобальных блокировок, асинхронной логики и интеграции с пользовательскими диалогами.