Route API

Route API является центральным элементом TanStack Router, обеспечивая декларативное управление маршрутизацией и навигацией в приложениях на JavaScript. Он позволяет создавать маршруты, организовывать их в иерархии, управлять параметрами, асинхронной загрузкой данных и защитой маршрутов.

Создание маршрутов

Маршрут в TanStack Router описывается с помощью объекта Route. Основные свойства объекта:

  • path — строка, задающая путь маршрута. Поддерживаются динамические сегменты, например: /users/:userId.
  • component — компонент, который будет отрендерен при совпадении маршрута.
  • loader — функция, возвращающая данные для маршрута до рендера компонента.
  • children — массив вложенных маршрутов, создающих иерархию.
  • action — функция для обработки событий, например, форм.
  • beforeEnter — хук, позволяющий выполнять проверки или перенаправления до активации маршрута.

Пример базового маршрута:

import { Route } from '@tanstack/router';
import UserPage from './pages/UserPage';

const userRoute = new Route({
  path: '/users/:userId',
  component: UserPage,
  loader: async ({ params }) => {
    const response = await fetch(`/api/users/${params.userId}`);
    return response.json();
  },
});

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

Динамические сегменты обозначаются двоеточием (:param). Они автоматически становятся частью объекта params, доступного в loader, action и компоненте через хук useParams.

const postRoute = new Route({
  path: '/posts/:postId',
  component: PostPage,
  loader: async ({ params }) => {
    return fetch(`/api/posts/${params.postId}`).then(res => res.json());
  },
});

Можно использовать несколько динамических сегментов и комбинировать их с фиксированными частями пути, например: /users/:userId/posts/:postId.

Вложенные маршруты

Иерархия маршрутов позволяет создавать сложные структуры с вложенной навигацией. Вложенные маршруты наследуют параметры родителей и могут иметь свои собственные loader и component.

const appRoute = new Route({
  path: '/',
  component: AppLayout,
  children: [
    new Route({
      path: 'dashboard',
      component: DashboardPage,
    }),
    new Route({
      path: 'settings',
      component: SettingsPage,
    }),
  ],
});

Вложенные маршруты рендерятся внутри родительского компонента через <Outlet />.

Ленивая загрузка и асинхронные компоненты

TanStack Router поддерживает ленивую загрузку компонентов с помощью динамического импорта. Это улучшает производительность и уменьшает размер начального бандла.

const lazyRoute = new Route({
  path: '/lazy',
  component: async () => {
    const module = await import('./pages/LazyPage');
    return module.default;
  },
});

Защита маршрутов и редиректы

Хук beforeEnter позволяет проверять условия доступа и выполнять перенаправления. Он может быть асинхронным и возвращать объект с redirectTo.

const protectedRoute = new Route({
  path: '/admin',
  component: AdminPage,
  beforeEnter: async ({ context }) => {
    if (!context.user?.isAdmin) {
      return { redirectTo: '/login' };
    }
  },
});

Actions и обработка форм

Action функции позволяют обрабатывать POST-запросы и другие действия, не изменяя состояние маршрута напрямую. Они интегрируются с формами:

const createPostRoute = new Route({
  path: '/posts/new',
  component: CreatePostPage,
  action: async ({ request }) => {
    const formData = await request.formData();
    await fetch('/api/posts', {
      method: 'POST',
      body: formData,
    });
  },
});

Навигация через Route API

Маршруты создают объект, который можно использовать для программной навигации:

  • router.navigate({ to: route, params: {...} }) — переход к маршруту с передачей параметров.
  • router.prefetch(route) — предзагрузка данных маршрута до навигации.
  • useRouter — хук для доступа к экземпляру роутера внутри компонентов.

Работа с контекстом

Контекст маршрута позволяет хранить данные, доступные всем дочерним маршрутам. Он задается через context при создании маршрута и доступен через useRouteContext или внутри loader и action.

const appRoute = new Route({
  path: '/',
  component: AppLayout,
  context: { user: null },
  children: [
    new Route({
      path: 'profile',
      component: ProfilePage,
    }),
  ],
});

Контекст можно обновлять динамически через router.updateContext.

Итоговая структура маршрутов

Эффективная организация маршрутов с Route API предполагает:

  • Чёткое определение иерархии и вложенности.
  • Использование динамических сегментов для параметризации.
  • Применение loader для асинхронной загрузки данных.
  • Обеспечение безопасности через beforeEnter.
  • Ленивая загрузка компонентов для оптимизации производительности.
  • Контекст для передачи данных через дерево маршрутов.

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