Пользовательские валидаторы

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

Основы валидаторов

Каждый валидатор — это функция или объект с методами, которые определяют, как проверять и преобразовывать данные. Валидаторы могут применяться к параметрам маршрута (params) или к строкам запроса (search).

Пример структуры валидатора для параметра маршрута:

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

const intValidator = {
  parse: (value) => {
    const parsed = parseInt(value, 10);
    if (isNaN(parsed)) throw new Error('Некорректное значение числа');
    return parsed;
  },
  stringify: (value) => value.toString(),
};
  • parse — функция, которая преобразует строковое значение из URL в нужный тип данных.
  • stringify — функция, которая преобразует значение обратно в строку для формирования URL.

Применение валидаторов к маршрутам

При определении маршрута валидаторы подключаются через опцию params. Это обеспечивает автоматическую проверку и преобразование параметров при навигации.

const userRoute = createRoute({
  path: '/user/:userId',
  params: {
    userId: intValidator,
  },
  component: UserPage,
});

В этом примере параметр userId будет автоматически преобразован в число при доступе к маршруту. Если значение некорректное, TanStack Router выбросит исключение или вызовет fallback-логику, если она предусмотрена.

Комбинирование валидаторов

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

const rangeValidator = {
  parse: (value) => {
    const num = parseInt(value, 10);
    if (isNaN(num) || num < 1 || num > 100) throw new Error('Значение должно быть от 1 до 100');
    return num;
  },
  stringify: (value) => value.toString(),
};

Такой валидатор можно использовать как для параметров маршрута, так и для query-параметров.

Асинхронные валидаторы

В некоторых сценариях необходимо выполнять проверку данных асинхронно, например, проверять существование пользователя в базе данных. Для этого TanStack Router позволяет возвращать из parse промис:

const asyncUserValidator = {
  parse: async (value) => {
    const user = await fetchUserById(value);
    if (!user) throw new Error('Пользователь не найден');
    return user.id;
  },
  stringify: (value) => value.toString(),
};

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

Валидация query-параметров

Query-параметры можно валидировать аналогично параметрам маршрута. Для этого при создании маршрута используется объект search.

const productsRoute = createRoute({
  path: '/products',
  search: {
    page: rangeValidator,
    sort: {
      parse: (value) => ['asc', 'desc'].includes(value) ? value : 'asc',
      stringify: (value) => value,
    },
  },
  component: ProductsPage,
});

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

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

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

const userRoute = createRoute({
  path: '/user/:userId',
  params: {
    userId: intValidator,
  },
  component: UserPage,
  onValidateError: ({ error, navigate }) => {
    console.error(error);
    navigate('/error');
  },
});

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

В TypeScript валидаторы позволяют строго типизировать параметры маршрута, что улучшает автокомплит и предотвращает ошибки на этапе компиляции:

const intValidator = {
  parse: (value: string): number => {
    const parsed = parseInt(value, 10);
    if (isNaN(parsed)) throw new Error('Некорректное число');
    return parsed;
  },
  stringify: (value: number): string => value.toString(),
};

const route = createRoute<{
  params: { userId: number };
}>({
  path: '/user/:userId',
  params: { userId: intValidator },
  component: UserPage,
});

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

Преобразование и нормализация данных

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

const slugValidator = {
  parse: (value) => value.trim().toLowerCase(),
  stringify: (value) => value,
};

Это гарантирует единообразие данных и упрощает работу с URL.

Резюме по применению

  • Валидаторы обеспечивают проверку и преобразование параметров URL.
  • Они могут быть синхронными и асинхронными.
  • Поддерживаются для параметров маршрута (params) и query-параметров (search).
  • Ошибки валидаторов можно обрабатывать локально или глобально.
  • Интеграция с TypeScript повышает безопасность и удобство разработки.
  • Нормализация данных через валидаторы упрощает обработку URL и предотвращает баги.

Пользовательские валидаторы в TanStack Router делают маршрутизацию гибкой, безопасной и предсказуемой, превращая работу с параметрами URL в полностью управляемый процесс.