Фильтрация и поиск

React Aria предоставляет набор хуков и утилит для создания доступных пользовательских интерфейсов. Среди них ключевую роль играют возможности фильтрации и поиска, которые позволяют реализовать динамическую подстройку контента под ввод пользователя с соблюдением стандартов доступности (ARIA).

Фильтрация и поиск обычно применяются в компонентах типа списков, выпадающих меню, таблиц или комбинированных полей ввода. Основной принцип работы заключается в разделении логики состояния и представления: React Aria предоставляет доступные события, свойства и методы управления, а визуальное оформление остаётся на стороне разработчика.


Хуки для поиска и фильтрации

useFilter

useFilter — это утилита для фильтрации коллекций элементов на основе строки поиска. Она возвращает функцию contains, которая может использоваться для проверки, соответствует ли элемент заданному фильтру.

Пример использования:

import {useFilter} from '@react-aria/i18n';

const {contains} = useFilter({sensitivity: 'base', ignoreCase: true});
const filteredItems = items.filter(item => contains(item.name, searchTerm));

Параметры useFilter:

  • sensitivity: Определяет чувствительность к регистру и диакритическим знакам. Возможные значения: 'base', 'accent', 'case', 'variant'.
  • ignoreCase: Булево значение, указывающее игнорировать ли регистр при сравнении.

Использование useFilter упрощает реализацию поиска без необходимости вручную писать функции сравнения и заботиться о локализации.


useComboBox и фильтрация

Для выпадающих списков с поиском (ComboBox) React Aria предоставляет хук useComboBox, который можно интегрировать с useFilter для динамического отбора элементов.

Пример:

import {useComboBoxState} from '@react-stately/combobox';
import {useComboBox} from '@react-aria/combobox';
import {useFilter} from '@react-aria/i18n';

function SearchableComboBox({items}) {
  const {contains} = useFilter({sensitivity: 'base'});
  const state = useComboBoxState({
    items,
    defaultFilter: (item, inputValue) => contains(item.name, inputValue),
  });

  const ref = React.useRef();
  const {inputProps, listBoxProps, labelProps} = useComboBox({inputRef: ref}, state);

  return (
    
{state.isOpen && (
    {state.filteredItems.map(item => (
  • {item.name}
  • ))}
)}
); }

Здесь defaultFilter использует функцию contains для проверки соответствия каждого элемента введённой строке поиска.


Фильтрация сложных данных

React Aria поддерживает фильтрацию не только по простым строкам, но и по более сложным структурам. Для этого можно использовать кастомные функции фильтрации в сочетании с useComboBoxState или useListState:

const customFilter = (item, inputValue) => {
  const nameMatch = contains(item.name, inputValue);
  const descriptionMatch = contains(item.description, inputValue);
  return nameMatch || descriptionMatch;
};

const state = useListState({
  items,
  defaultFilter: customFilter,
});

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


Оптимизация производительности

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

  • Использовать мемоизацию фильтрации через React.useMemo, чтобы не пересчитывать результат при каждом ререндере.
  • Ограничивать количество отображаемых элементов с помощью виртуализации (react-virtual или аналогичные библиотеки).
  • Фильтровать элементы только при изменении строки поиска, а не на каждый ререндер.

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

const filteredItems = React.useMemo(() => {
  return items.filter(item => contains(item.name, searchTerm));
}, [items, searchTerm, contains]);

Доступность и ARIA

React Aria гарантирует корректное применение ARIA-атрибутов для компонентов поиска и фильтрации:

  • aria-activedescendant для указания текущего выбранного элемента в списке.
  • aria-controls для связи поля ввода с контейнером списка.
  • aria-expanded для отражения состояния раскрытия списка.
  • aria-label или aria-labelledby для описания назначения поля поиска.

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


Расширенные возможности поиска

  • Поддержка diacritics и локализации: useFilter учитывает локальные правила сортировки и поиска, позволяя корректно работать с языками, где есть диакритические знаки.
  • Настраиваемые методы фильтрации: можно передавать кастомные функции filterFn в useListState или useComboBoxState для реализации сложных алгоритмов поиска (регулярные выражения, fuzzy search).
  • Интеграция с Virtualized Lists: фильтрация может работать совместно с виртуализированными списками, что критично при отображении тысяч элементов.