useSelectableCollection для выделения

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

Хук возвращает объект с состоянием коллекции и методами для управления выделением, фокусом и событиями навигации. Основная идея заключается в том, чтобы отделить логику доступности от визуального представления элементов.


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

import { useSelectableCollection } from "@react-aria/selection";
import { useListState } from "@react-stately/list";

const MySelectableList = ({ items }) => {
  const state = useListState({ items });
  const ref = React.useRef();

  const { collectionProps, selectionManager } = useSelectableCollection({
    selectionMode: "multiple",
    disallowEmptySelection: true,
    ref,
    collection: state.collection
  });

  return (
    <ul {...collectionProps} ref={ref}>
      {state.collection.items.map(item => (
        <li key={item.key}>
          {item.rendered}
        </li>
      ))}
    </ul>
  );
};

Ключевые моменты:

  • selectionMode: "single" или "multiple". Определяет, сколько элементов может быть выделено одновременно.
  • disallowEmptySelection: запрещает снятие выделения со всех элементов, если установлено в true.
  • collection: коллекция элементов, обычно управляется через useListState.
  • ref: ссылка на корневой DOM-элемент коллекции.

Работа с selectionManager

selectionManager — это объект, который предоставляет методы для управления выделением и навигацией:

  • isSelected(key) — проверяет, выделен ли элемент с указанным ключом.
  • sel ect(key) — выделяет элемент.
  • toggleSelection(key) — переключает состояние выделения.
  • setSelectedKeys(keys) — задаёт новые выделенные элементы (поддерживает множественный выбор).
  • focusItem(key) — устанавливает фокус на элемент с ключом key.
  • toggleFocus(key) — переключает фокус на элемент.

Пример использования для программного выделения элемента:

selectionManager.select("item-3"); // выделяет элемент с ключом "item-3"
selectionManager.focusItem("item-2"); // устанавливает фокус на "item-2"

Настройка взаимодействия с клавиатурой

Хук useSelectableCollection автоматически обрабатывает навигацию с клавиатуры, если элементы подключены к collectionProps и ref. Поддерживаются:

  • Стрелки вверх/вниз для перемещения по элементам.
  • Пробел и Enter для выбора элемента.
  • Shift + стрелки для расширения выделения при multiple режиме.

Для кастомной логики можно использовать selectionManager.focusNextKey() или selectionManager.focusPreviousKey().


Интеграция с useListState и Collection

useSelectableCollection тесно интегрируется с @react-stately/collections. Это позволяет управлять динамическими коллекциями и синхронизировать состояние выделения:

import { useListState } fr om "@react-stately/list";

const items = [
  { id: '1', name: 'Элемент 1' },
  { id: '2', name: 'Элемент 2' },
  { id: '3', name: 'Элемент 3' },
];

const state = useListState({ items });
const { collectionProps, selectionManager } = useSelectableCollection({
  collection: state.collection,
  selectionMode: "multiple",
});

Преимущества интеграции:

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

Состояния элементов

Для визуального отображения выделения и фокуса можно использовать состояние selectionManager:

<li
  key={item.key}
  className={`${selectionManager.isSelected(item.key) ? 'selected' : ''} ${
    selectionManager.focusedKey === item.key ? 'focused' : ''
  }`}
>
  {item.rendered}
</li>
  • isSelected(key) — выделенный элемент.
  • focusedKey — элемент с текущим фокусом.

Это позволяет легко стилизовать выбранные элементы и элементы с фокусом.


Продвинутая настройка

useSelectableCollection поддерживает дополнительные параметры:

  • selectionBehavior: "toggle" или "replace". Определяет, как будут реагировать клики на выделение.
  • shouldFocusOnHover: true | false. Фокус при наведении мыши.
  • keyboardDelegate: кастомный объект, который переопределяет навигацию клавишами.

Пример использования кастомного поведения выделения:

const { collectionProps } = useSelectableCollection({
  collection: state.collection,
  selectionMode: "multiple",
  selectionBehavior: "toggle", // каждый клик переключает выделение
});

Использование с компонентами React

useSelectableCollection идеально подходит для интеграции с:

  • Списками (<ul> / <li>).
  • Таблицами (<table> / <tr> / <td>).
  • Грид-галереями.
  • Меню и кастомными дропдаунами.

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


Резюме ключевых возможностей

  • Управление выделением (single / multiple).
  • Полная поддержка клавиатуры и ассистивных технологий.
  • Интеграция с useListState и динамическими коллекциями.
  • Программное управление выделением и фокусом через selectionManager.
  • Поддержка кастомных поведений через selectionBehavior и keyboardDelegate.

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