useSearch для работы с query params

useSearch — это хук, предоставляемый TanStack Router, который позволяет удобно работать с параметрами запроса (query parameters) в URL. Он обеспечивает синхронизацию состояния приложения с адресной строкой и упрощает управление динамическими фильтрами, сортировками и другими данными, передаваемыми через URL.


Основные принципы работы

Хук useSearch возвращает объект, содержащий текущие значения query-параметров, и функции для их обновления. Он позволяет:

  • Читать текущие query-параметры.
  • Обновлять один или несколько параметров без перезагрузки страницы.
  • Сохранять типизацию данных, что особенно важно для сложных форм и фильтров.

Синтаксис базового использования:

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

const Component = () => {
  const [search, setSearch] = useSearch({ initialValues: { page: 1, sort: 'asc' } });

  // чтение параметров
  console.log(search.page, search.sort);

  // обновление параметров
  const goToNextPage = () => setSearch({ page: search.page + 1 });
};

Типизация параметров

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

Пример строгой типизации:

type SearchParams = {
  page: number;
  filter: string;
  sort: 'asc' | 'desc';
};

const [search, setSearch] = useSearch<SearchParams>({
  initialValues: { page: 1, filter: '', sort: 'asc' },
});

В этом примере TypeScript гарантирует, что:

  • page всегда число.
  • sort может принимать только 'asc' или 'desc'.
  • Любая попытка задать недопустимое значение вызовет ошибку на этапе компиляции.

Установка начальных значений

useSearch позволяет задавать начальные значения через объект initialValues. Если URL уже содержит соответствующие query-параметры, они имеют приоритет над начальными значениями.

const [search, setSearch] = useSearch({
  initialValues: { page: 1, filter: 'all', sort: 'asc' },
});

Если пользователь вручную введет в URL ?page=3&sort=desc, search автоматически отобразит эти значения.


Обновление параметров

Для изменения query-параметров используется функция setSearch. Она поддерживает:

  1. Полную замену всех параметров:
setSearch({ page: 2, filter: 'completed', sort: 'desc' });
  1. Частичное обновление с сохранением существующих параметров:
setSearch(prev => ({ ...prev, page: prev.page + 1 }));
  1. Удаление параметров, если установить их в undefined:
setSearch({ filter: undefined });

После обновления URL автоматически синхронизируется с состоянием хука без перезагрузки страницы.


Реактивность и эффекты

useSearch можно использовать совместно с useEffect для реакции на изменения query-параметров:

import { useEffect } from 'react';

useEffect(() => {
  fetchData(search);
}, [search]);

Любое изменение query-параметров запускает эффект, что идеально подходит для динамической подгрузки данных при фильтрации или пагинации.


Работа с массивами и сложными типами

TanStack Router позволяет использовать массивы и другие сложные типы в query-параметрах. Для этого их необходимо сериализовать/десериализовать через initialValues и функции setSearch.

type SearchParams = {
  tags: string[];
};

const [search, setSearch] = useSearch<SearchParams>({
  initialValues: { tags: [] },
});

setSearch({ tags: ['react', 'router'] });

URL автоматически преобразует массив в строку ?tags=react,tanstack и обратно при чтении.


Советы по использованию

  • Использовать initialValues для обеспечения безопасных дефолтных состояний.
  • Типизировать query-параметры для предотвращения ошибок.
  • Использовать функциональный вариант setSearch(prev => ...) для сложных обновлений.
  • Обрабатывать удаление параметров через undefined, чтобы URL оставался чистым.
  • Для массивов и объектов продумывать стратегию сериализации/десериализации.

Пример комплексного компонента с фильтрацией и пагинацией

type SearchParams = {
  page: number;
  query: string;
  tags: string[];
};

const FilterableList = () => {
  const [search, setSearch] = useSearch<SearchParams>({
    initialValues: { page: 1, query: '', tags: [] },
  });

  const handleSearchChange = (query: string) => setSearch(prev => ({ ...prev, query, page: 1 }));
  const handleTagToggle = (tag: string) => {
    setSearch(prev => ({
      ...prev,
      tags: prev.tags.includes(tag)
        ? prev.tags.filter(t => t !== tag)
        : [...prev.tags, tag],
    }));
  };
  const nextPage = () => setSearch(prev => ({ ...prev, page: prev.page + 1 }));

  useEffect(() => {
    fetchItems(search);
  }, [search]);

  return (
    <div>
      {/* UI для ввода query и выбора тегов */}
      <button onCl ick={nextPage}>Next Page</button>
    </div>
  );
};

В этом примере useSearch обеспечивает полный контроль над query-параметрами, синхронизацию с URL и типобезопасность всех операций.


useSearch делает работу с query-параметрами в TanStack Router простой, предсказуемой и безопасной, обеспечивая мощные возможности для управления состоянием URL и динамических интерфейсов.