Фильтры с множественными значениями

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

Определение маршрута с поддержкой массивов

Для работы с фильтрами, где одно поле может принимать несколько значений, используется тип string[] в параметрах запроса:

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

const productsRoute = createRoute({
  path: '/products',
  component: ProductsPage,
  searchSchema: {
    category: {
      type: 'array', // массив строк
      default: []
    },
    color: {
      type: 'array',
      default: []
    }
  }
});

const router = createRouter({
  routeTree: productsRoute
});

В этом примере category и color определены как массивы строк, что позволяет одновременно фильтровать товары по нескольким категориям и цветам.

Чтение и запись фильтров

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

function ProductsPage({ search }) {
  const { category, color } = search;

  console.log(category); // ['electronics', 'appliances']
  console.log(color);    // ['red', 'blue']

  return (
    <div>
      <Filters selectedCategories={category} selectedColors={color} />
      <ProductList filters={{ category, color }} />
    </div>
  );
}

Для обновления фильтров используется метод router.navigate с передачей новых массивов значений:

function toggleCategory(categoryValue) {
  const newCategories = category.includes(categoryValue)
    ? category.filter(c => c !== categoryValue)
    : [...category, categoryValue];

  router.navigate({ search: { ...search, category: newCategories } });
}

При изменении массива URL автоматически синхронизируется с состоянием, и компоненты, использующие search, получают обновленные данные.

Сериализация массивов в URL

TanStack Router поддерживает несколько форматов сериализации массивов:

  • CSV (по умолчанию): /products?category=electronics,appliances&color=red,blue
  • Повторяющиеся ключи: /products?category=electronics&category=appliances&color=red&color=blue
  • JSON-подобная сериализация: /products?category=["electronics","appliances"]

Формат можно настроить через searchSerializer при создании маршрута:

const productsRoute = createRoute({
  path: '/products',
  component: ProductsPage,
  searchSchema: {
    category: { type: 'array', default: [] },
    color: { type: 'array', default: [] }
  },
  searchSerializer: {
    category: (value) => value.join(','), // CSV
    color: (value) => value.join(',')
  }
});

Использование фильтров с зависимыми массивами

Иногда значения одного фильтра зависят от другого. Например, выбор категории может влиять на доступные цвета:

const availableColors = {
  electronics: ['black', 'silver'],
  appliances: ['white', 'red']
};

const filteredColors = category.flatMap(cat => availableColors[cat] || []);
const selectedColors = color.filter(c => filteredColors.includes(c));

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

Поддержка нескольких фильтров в интерфейсе

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

function MultiSelectFilter({ options, selectedValues, onChange }) {
  return (
    <div>
      {options.map(option => (
        <label key={option}>
          <input
            type="checkbox"
            checked={selectedValues.includes(option)}
            onCha nge={() => onChange(option)}
          />
          {option}
        </label>
      ))}
    </div>
  );
}

Передавая toggleCategory или аналогичные функции для других фильтров, можно синхронизировать состояние массива с URL.

Синхронизация с состоянием приложения

Для более сложных приложений рекомендуется хранить фильтры в глобальном состоянии или использовать React Query совместно с TanStack Router. Это позволяет:

  • Загружать данные при изменении фильтров автоматически.
  • Кешировать результаты запросов для ускорения повторного отображения.
  • Управлять зависимостями фильтров между различными страницами и компонентами.
import { useQuery } from '@tanstack/react-query';

const { data: products } = useQuery(
  ['products', search],
  () => fetchProducts(search)
);

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

Вывод

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