useListState для состояния списков

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


Основные возможности useListState

  1. Выбор элементов (selection) Хук поддерживает разные режимы выбора:

    • single — одиночный выбор.
    • multiple — множественный выбор с возможностью удержания клавиши Ctrl/Shift.
    • none — отключение выбора, полезно для статических списков.

    Выбор управляется через объект selectionState, который возвращает хук.

  2. Фильтрация элементов (filtering) Состояние списка может быть динамически отфильтровано на основе строки поиска или других условий. useListState автоматически обновляет список видимых элементов, сохраняя корректность индексов и ключей.

  3. Поддержка виртуализации (virtualization) Для длинных списков хук может использоваться совместно с компонентами виртуализации, так как возвращает полностью управляемый массив элементов с их состояниями, включая выделение и фокус.

  4. Управление фокусом (focus management) Хук хранит индекс текущего фокусированного элемента, обеспечивая корректное взаимодействие с клавиатурой. Методы setFocusedKey и isFocused позволяют синхронизировать фокус с DOM.


Синтаксис и базовое использование

import { useListState } from '@react-stately/list';

const listState = useListState({
  selectionMode: 'multiple',   // режим выбора: single | multiple | none
  initialSelectedKeys: ['item1'], // начально выбранные элементы
  items: [
    { id: 'item1', name: 'Первый элемент' },
    { id: 'item2', name: 'Второй элемент' },
    { id: 'item3', name: 'Третий элемент' }
  ]
});

useListState возвращает объект, содержащий:

  • collection — упорядоченный набор элементов списка с уникальными ключами.
  • selectionManager — объект для работы с выбором: isSelected, toggleKey, replaceSelection, clearSelection.
  • focusedKey — ключ текущего фокусированного элемента.
  • setFocusedKey(key) — функция для установки фокуса.
  • selectedKeys — набор выбранных ключей (Set).

Работа с выбором элементов

Проверка выделения

listState.selectionManager.isSelected('item2'); // true/false

Выбор и снятие выбора

listState.selectionManager.toggleKey('item2'); // переключение состояния выбора
listState.selectionManager.replaceSelection('item3'); // замена текущего выбора
listState.selectionManager.clearSelection(); // очистка выбора

Поддержка множественного выбора с клавиатурой

useListState автоматически учитывает модификаторы клавиш при работе с элементами списка:

  • Shift + Arrow Up/Down — расширение диапазона выбора.
  • Ctrl/Cmd + Click — добавление или удаление элемента из выбора без сброса текущего выбора.

Фокус и навигация

useListState хранит focusedKey и предоставляет методы для управления фокусом:

listState.setFocusedKey('item2'); // перемещение фокуса
const isFocused = listState.focusedKey === 'item2';

Фокус используется совместно с useListBox или любым кастомным компонентом для визуального выделения активного элемента и управления навигацией с клавиатуры.


Работа с коллекцией элементов

Объект collection возвращает полную структуру элементов, включая ключи и пользовательские данные:

listState.collection.forEach(item => {
  console.log(item.key, item.props.name);
});

Это позволяет легко рендерить список через map, сохраняя согласованность состояния выбора и фокуса.


Фильтрация и динамическое обновление

useListState поддерживает изменение списка элементов после инициализации:

listState.items = [
  { id: 'item1', name: 'Первый элемент' },
  { id: 'item4', name: 'Новый элемент' }
];

Хук автоматически обновляет:

  • доступные ключи элементов,
  • выделение (сбрасывает отсутствующие ключи),
  • индекс фокуса, если текущий элемент удалён.

Интеграция с компонентами React Aria

useListState часто используется совместно с компонентами:

  • useListBox — для рендеринга списка с поддержкой клавиатуры и WAI-ARIA атрибутов.
  • useOption — для отдельного элемента списка, синхронизированного с selectionManager.
  • useComboBox / useMenu — для управления состоянием выпадающих списков и автокомплита.

Пример интеграции с useListBox:

import { useListBox } from '@react-aria/listbox';

function ListBox({ state }) {
  const ref = React.useRef();
  const { listBoxProps } = useListBox({ selectionMode: state.selectionMode }, state, ref);

  return (
    <ul {...listBoxProps} ref={ref}>
      {[...state.collection].map(item => (
        <Option key={item.key} item={item} state={state} />
      ))}
    </ul>
  );
}

Ключевые преимущества использования useListState

  • Полная абстракция над логикой выбора, фильтрации и управления фокусом.
  • Поддержка всех режимов выбора и взаимодействий с клавиатурой.
  • Простая интеграция с другими хуками React Aria (useListBox, useOption, useComboBox).
  • Автоматическое управление изменениями коллекции и синхронизация состояния.
  • Удобство при работе с динамическими и виртуализированными списками.

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