Tanstack Router: первые впечатления от TypeScript-first роутера

#react#routing#typescript#tanstack

TL;DR

Tanstack Router позиционируется как TypeScript-first решение для маршрутизации с лучшей в классе типобезопасностью. Однако стартовый шаблон содержит несколько досадных недочетов - от проблем с Biome до неработающих компонентов в демо. Разбираем первые 20 минут знакомства с роутером.

Введение: новый игрок на поле маршрутизации

С появлением Tanstack Router (ранее React Location) фронтенд-сообщество получило альтернативу классическому React Router. Основной козырь - глубокая интеграция с TypeScript и декларативный API. Но как обстоят дела на практике?

Разбор стартового шаблона

Инициализация проекта выглядит стандартно:

npx @tanstack/cli create --router-only

После выбора Biome (альтернатива ESLint) получаем базовую структуру:

src/
  routes/
    _root.tsx
    index.tsx
  components/
    Header.tsx
    Footer.tsx

Проблема 1: TypeScript config

В tsconfig.json сразу бросается в глаза устаревший параметр:

{
  "compilerOptions": {
    "baseUrl": "./" // Устарело в TS 7+
  }
}

Фикс прост - замена на paths, но для новичка это может стать неочевидной ошибкой.

Проблема 2: Biome linting

Tanstack предусмотрительно добавляет скрипты для Biome:

{
  "scripts": {
    "lint": "biome lint src",
    "format": "biome format src"
  }
}

Но при запуске получаем кучу ошибок стиля. Демо-код не соответствует конфигурации Biome из коробки.

Проблема 3: “Мертвые” компоненты

В демо-приложении есть инструкция:

// Update src/components/Header.tsx and src/components/Footer.tsx

Но эти компоненты нигде не используются в _root.tsx. Ожидаешь увидеть базовый layout, а получаешь:

export const Route = createRootRoute({
  component: () => (
    <div className="p-2">
      <Link to="/" className="[&.active]:font-bold">
        Home
      </Link>
      <Outlet />
    </div>
  ),
});

Сравнение с React Router

Основные преимущества Tanstack Router:

  1. Типобезопасность маршрутов:
const postsRoute = createRoute({
  path: "posts",
  component: PostsPage,
  validateSearch: (search: Record<string, unknown>): { page: number } => {
    return {
      page: Number(search?.page) || 1,
    };
  },
});
  1. Загрузка данных в роутах:
{
  loader: async ({ params }) => {
    return fetchPost(params.postId);
  }
}
  1. Интеграция с Tanstack Query:
{
  useLoader: ({ loaderDeps }) => {
    return useQuery({
      queryKey: ["post", loaderDeps.postId],
      queryFn: () => fetchPost(loaderDeps.postId),
    });
  }
}

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

Несмотря на стартовые проблемы, Tanstack Router отлично подходит для:

  1. Крупных TypeScript-проектов
  2. Приложений с комплексной маршрутизацией
  3. Проектов, уже использующих Tanstack Query

Пример защиты маршрутов:

const authenticatedRoute = createRoute({
  path: "/dashboard",
  component: Dashboard,
  beforeLoad: ({ context }) => {
    if (!context.auth.isAuthenticated) {
      throw redirect({
        to: "/login",
      });
    }
  },
});

Заключение

Tanstack Router - мощное решение с акцентом на типобезопасность, но стартовый опыт мог бы быть более отполированным. Для небольших проектов React Router пока проще в освоении, но для enterprise-решений Tanstack определенно заслуживает внимания.

Что исправить в стартовом шаблоне:

  1. Актуализировать TS конфиг
  2. Настроить Biome правила под демо-код
  3. Добавить базовый layout с Header/Footer
  4. Документировать процесс настройки linting

Несмотря на мелкие недочеты, роутер демонстрирует современный подход к маршрутизации и достоин внимания senior-разработчиков.


Источник: https://www.reddit.com/r/reactjs/comments/1sfa3us/the_first_20_minutes_of_using_tanstack_router/