Сохранение redirect URL

В веб-приложениях часто возникает необходимость после авторизации или выполнения определённого действия возвращать пользователя на страницу, с которой он пришёл. TanStack Router предоставляет гибкие механизмы для работы с редиректами и сохранением исходного URL.


Использование состояния маршрута для хранения исходного URL

Каждый маршрут в TanStack Router может хранить состояние через объект state. Для сохранения redirect URL чаще всего используют ключ from, который указывает исходный путь пользователя до перенаправления.

Пример:

import { useNavigate, useLocation } from '@tanstack/router';

function Login() {
  const navigate = useNavigate();
  const location = useLocation();

  const handleLogin = async () => {
    await performLogin();

    // Определяем исходный путь
    const redirectTo = location.state?.from || '/dashboard';
    navigate({ to: redirectTo });
  };

  return (
    <button onCl ick={handleLogin}>Войти</button>
  );
}

В этом примере при переходе на страницу логина можно передавать исходный путь через state:

navigate({ to: '/login', state: { from: location.pathname } });

Таким образом, после успешной авторизации пользователь автоматически вернётся на страницу, с которой начинал работу.


Хранение redirect URL через query-параметры

Другой подход — передавать URL через query-параметры. Это полезно, когда состояние маршрута не сохраняется при перезагрузке страницы:

import { useSearch } from '@tanstack/router';

function Login() {
  const search = useSearch();
  const navigate = useNavigate();

  const handleLogin = async () => {
    await performLogin();

    const redirectTo = search.redirect || '/dashboard';
    navigate({ to: redirectTo });
  };

  return (
    <button onCl ick={handleLogin}>Войти</button>
  );
}

Переход на страницу логина с сохранением исходного URL:

navigate({ to: '/login', search: { redirect: location.pathname } });

Преимущество такого метода — URL всегда виден в адресной строке и доступен после полной перезагрузки страницы.


Комбинация loader и редиректов для защищённых маршрутов

TanStack Router позволяет использовать асинхронные loader функции для проверки доступа к маршруту. Если пользователь не авторизован, loader может инициировать редирект с сохранением исходного пути:

import { redirect } from '@tanstack/router';

async function protectedLoader({ context, params }) {
  const user = await context.getCurrentUser();
  if (!user) {
    return redirect('/login', { state: { from: window.location.pathname } });
  }
  return user;
}

Здесь redirect передаёт исходный путь через state, что позволяет после авторизации вернуть пользователя обратно.


Использование middleware для глобального редиректа

Для крупных приложений удобнее централизованно обрабатывать редиректы через middleware. Это позволяет не дублировать логику проверки авторизации на каждом маршруте:

router.use(({ next }) => {
  const user = getCurrentUser();
  if (!user && next.route.meta.requiresAuth) {
    return redirect('/login', { state: { from: window.location.pathname } });
  }
  return next();
});

Такой подход делает маршрутизацию более предсказуемой и упрощает поддержку приложения.


Практические рекомендации

  • Выбор способа хранения URL:

    • state маршрута подходит для SPA без перезагрузок.
    • query-параметры удобны при необходимости сохранять URL после полной перезагрузки или в закладках.
  • Обработка отсутствующего redirect URL: Всегда указывайте fallback, например /dashboard, чтобы избежать ошибок при навигации.

  • Безопасность: Не используйте непроверенные внешние URL для редиректа, чтобы исключить открытые редиректы. Лучше проверять, что redirectTo принадлежит вашему приложению.


Эти подходы позволяют гибко управлять сохранением redirect URL в TanStack Router, обеспечивая корректную навигацию и удобство работы пользователя с приложением.