Переход с других роутеров

TanStack Router представляет собой современный подход к маршрутизации в приложениях на JavaScript и TypeScript. В отличие от классических роутеров, таких как React Router, он строится вокруг явного описания маршрутов, статических и динамических сегментов, а также первоклассной поддержки асинхронного получения данных.

Ключевые особенности:

  • Декларативная структура маршрутов: маршруты описываются объектами, а не JSX-компонентами, что упрощает работу с динамическими сегментами и вложенностью.
  • Типизация через TypeScript: маршруты и параметры строго типизированы, что уменьшает количество ошибок при работе с URL и параметрами.
  • Интеграция с загрузкой данных (loaders) и кэшированием: каждый маршрут может иметь собственный loader, который выполняется до рендеринга компонента.
  • Управление состоянием переходов: TanStack Router позволяет отслеживать состояние загрузки данных, перехода и ошибок на уровне каждого маршрута.

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

Маршрут в TanStack Router описывается объектом, который включает следующие ключевые поля:

const route = {
  path: '/users/:userId',
  component: UserPage,
  loader: async ({ params }) => {
    return fetchUser(params.userId);
  },
  children: [
    {
      path: 'posts',
      component: UserPosts,
      loader: async ({ params }) => fetchPosts(params.userId),
    }
  ],
};

Объяснение ключевых элементов:

  • path: путь маршрута с поддержкой динамических сегментов (:userId).
  • component: компонент, который рендерится для данного маршрута.
  • loader: асинхронная функция, вызываемая до рендеринга. Возвращаемые данные становятся доступными через хук useLoaderData.
  • children: вложенные маршруты, позволяющие строить иерархическую структуру.

Переход с React Router

React Router использует JSX-компоненты и для определения маршрутов, в то время как TanStack Router требует объектного описания маршрутов. Основные шаги при миграции:

  1. Переписать декларацию маршрутов:
// React Router

  } />
  } />


// TanStack Router
const routes = [
  {
    path: '/users/:id',
    component: UserPage,
    children: [
      { path: 'posts', component: UserPosts }
    ]
  }
];
  1. Переход с useParams на useParams TanStack Router: В TanStack Router доступ к параметрам маршрута осуществляется через встроенный хук:
import { useParams } from '@tanstack/router';

const params = useParams();
console.log(params.id);
  1. Обработка данных через loader вместо useEffect: Loader позволяет заранее загружать данные до рендеринга компонента, что упрощает работу с асинхронными запросами и устраняет лишние состояния загрузки.
const userRoute = {
  path: '/users/:id',
  component: UserPage,
  loader: async ({ params }) => {
    return fetch(`/api/users/${params.id}`).then(res => res.json());
  }
};

Работа с вложенными маршрутами

В отличие от многих старых роутеров, TanStack Router нативно поддерживает глубокую вложенность без необходимости ручного построения путей. Каждый дочерний маршрут автоматически наследует путь родителя:

const routes = [
  {
    path: '/dashboard',
    component: DashboardLayout,
    children: [
      {
        path: 'analytics',
        component: AnalyticsPage,
      },
      {
        path: 'settings',
        component: SettingsPage,
      }
    ]
  }
];

Доступ к маршруту dashboard/analytics выполняется автоматически через объектную структуру, и нет необходимости вручную конкатенировать пути.

Навигация и управление переходами

Вместо и navigate React Router, TanStack Router предоставляет:

  • useNavigate для программной навигации:
const navigate = useNavigate();
navigate({ to: '/users/42' });
  • Link компонент для декларативной навигации с типизацией:
Профиль пользователя
  • Статус перехода и загрузки данных через useIsPending:
const isPending = useIsPending();
if (isPending) {
  return ;
}

Обработка ошибок и редиректов

TanStack Router позволяет задавать маршрутные обработчики ошибок:

const errorRoute = {
  path: '*',
  component: NotFoundPage,
};

const protectedRoute = {
  path: '/admin',
  component: AdminPage,
  loader: async () => {
    const isAdmin = await checkAdmin();
    if (!isAdmin) throw new Response('Unauthorized', { status: 401 });
  },
  errorComponent: UnauthorizedPage,
};

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

Поддержка TypeScript и строгость маршрутов

TanStack Router полностью интегрирован с TypeScript:

  • Параметры маршрута строго типизированы.
  • Возможность заранее определить типы данных, которые возвращает loader.
  • Компилятор проверяет корректность всех ссылок на маршруты, предотвращая ошибки на этапе разработки.

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

interface UserParams {
  userId: string;
}

const userRoute = new Route({
  path: '/users/:userId',
  component: UserPage,
  loader: async ({ params }) => fetchUser(params.userId),
});

Такой подход обеспечивает полную безопасность при переходах и работе с данными, чего сложно достичь в классических роутерах.