Редиректы и перенаправления

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


Конфигурация маршрутов с редиректом

Редирект реализуется через свойство redirect или через возвращаемое значение функции обработчика маршрута. Стандартный способ задания перенаправления выглядит следующим образом:

import UniversalRouter from 'universal-router';

const routes = [
  {
    path: '/old-path',
    redirect: '/new-path'
  },
  {
    path: '/new-path',
    action: () => 'Вы перешли на новый путь'
  }
];

const router = new UniversalRouter(routes);

router.resolve('/old-path').then(result => {
  console.log(result); // 'Вы перешли на новый путь'
});

В этом примере при попытке перейти на /old-path происходит автоматический редирект на /new-path. Важно понимать, что redirect может быть не только строкой, но и функцией, возвращающей строку или промис, что позволяет реализовать динамические перенаправления.


Динамические редиректы

Для более сложных сценариев можно использовать функции в качестве значения redirect:

const routes = [
  {
    path: '/profile/:id',
    redirect: (context) => {
      if (!context.user) {
        return '/login';
      }
      return `/dashboard/${context.user.id}`;
    }
  },
  {
    path: '/login',
    action: () => 'Страница логина'
  },
  {
    path: '/dashboard/:id',
    action: ({ params }) => `Профиль пользователя ${params.id}`
  }
];

const router = new UniversalRouter(routes);

router.resolve('/profile/123', { user: { id: 123 } })
  .then(console.log); // 'Профиль пользователя 123'

router.resolve('/profile/123', {}) 
  .then(console.log); // 'Страница логина'

Ключевой момент: функция redirect получает контекст context и объект параметров маршрута, что позволяет принимать решения о перенаправлении на основе состояния приложения, авторизации пользователя, данных из API и других условий.


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

Помимо свойства redirect, редирект можно реализовать внутри функции action маршрута, возвращая объект с полем redirect:

const routes = [
  {
    path: '/start',
    action: () => ({ redirect: '/home' })
  },
  {
    path: '/home',
    action: () => 'Главная страница'
  }
];

const router = new UniversalRouter(routes);

router.resolve('/start').then(console.log); // 'Главная страница'

Такой подход особенно удобен, когда редирект должен выполняться после выполнения каких-либо асинхронных операций: загрузки данных или проверки условий.


Редиректы с асинхронной логикой

Universal Router полностью поддерживает промисы, что позволяет делать редиректы на основе асинхронных операций:

const routes = [
  {
    path: '/secure',
    action: async (context) => {
      const isAuthenticated = await checkAuth(context);
      if (!isAuthenticated) {
        return { redirect: '/login' };
      }
      return 'Доступ к защищённой странице';
    }
  },
  {
    path: '/login',
    action: () => 'Страница входа'
  }
];

async function checkAuth(context) {
  // имитация асинхронной проверки авторизации
  return new Promise(resolve => setTimeout(() => resolve(false), 100));
}

const router = new UniversalRouter(routes);

router.resolve('/secure').then(console.log); // 'Страница входа'

Особенность: редирект через action позволяет учитывать сложную логику, которая не может быть выражена простым свойством redirect.


Обработка редиректов и цепочек маршрутов

При последовательных редиректах Universal Router автоматически следит за конечным целевым маршрутом. Например:

const routes = [
  { path: '/a', redirect: '/b' },
  { path: '/b', redirect: '/c' },
  { path: '/c', action: () => 'Финальная страница' }
];

const router = new UniversalRouter(routes);

router.resolve('/a').then(console.log); // 'Финальная страница'

Если редиректы создают циклическую зависимость, Universal Router выдаёт ошибку для предотвращения бесконечного цикла. Это важно учитывать при проектировании маршрутов.


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

  1. Использовать redirect для простых статических перенаправлений.
  2. Применять action с возвращаемым объектом { redirect: '...' } для асинхронных проверок или сложной логики.
  3. Всегда обрабатывать возможные циклы редиректов, чтобы избежать ошибок навигации.
  4. Для динамических маршрутов учитывать параметры и контекст при выборе целевого URL.

Редиректы в Universal Router дают гибкость и позволяют строить динамичную маршрутизацию, учитывая состояние приложения, авторизацию и другие условия. Они являются фундаментальной частью управления навигацией в современных SPA и универсальных приложениях на JavaScript.