useCollection для работы с коллекциями

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


Создание коллекции

Для использования useCollection требуется передать ему массив элементов или объект коллекции в формате:

import {useCollection} from '@react-aria/utils';

const items = [
  {id: '1', name: 'Item 1'},
  {id: '2', name: 'Item 2'},
  {id: '3', name: 'Item 3'}
];

const collection = useCollection(items, item => item.id);

Пояснения:

  • items — исходный массив объектов.
  • Второй аргумент (функция getKey) возвращает уникальный идентификатор элемента коллекции.
  • Результат useCollection — объект коллекции, включающий методы и свойства для удобного перебора, фильтрации и поиска элементов.

Структура объекта коллекции

Объект коллекции, возвращаемый useCollection, имеет несколько ключевых свойств:

  • items — массив объектов коллекции с добавленными метаданными, включая уникальные ключи и тип элементов.
  • getItem(key) — метод для получения конкретного элемента по ключу.
  • size — количество элементов в коллекции.
  • keys — массив всех ключей элементов коллекции.
  • map и forEach — функции для перебора коллекции аналогично стандартным методам массива.

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

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

const secondItem = collection.getItem('2');
console.log(secondItem.name); // "Item 2"

Работа с иерархическими коллекциями

useCollection поддерживает древовидные структуры, где элементы могут содержать дочерние элементы. Для этого достаточно передавать вложенный массив children:

const treeItems = [
  {id: '1', name: 'Parent 1', children: [
    {id: '1-1', name: 'Child 1-1'},
    {id: '1-2', name: 'Child 1-2'}
  ]},
  {id: '2', name: 'Parent 2'}
];

const treeCollection = useCollection(treeItems, item => item.id);

Теперь можно легко обходить элементы любого уровня вложенности:

treeCollection.items.forEach(item => {
  console.log(item.key, item.name, item.hasChildren ? 'Has children' : 'Leaf');
});

Особенности:

  • hasChildren — свойство автоматически добавляется к элементам с дочерними элементами.
  • children внутри элемента также представляют собой коллекцию, что упрощает интеграцию с хуками вроде useTreeState.

Интеграция с другими хуками React Aria

useCollection часто используется в сочетании с другими хуками для управления состоянием компонентов:

  1. С useListBox и useListState:
import {useListState} from '@react-stately/list';
import {useListBox} from '@react-aria/listbox';

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

const {listBoxProps} = useListBox({label: 'Example', selectionMode: 'single'}, state, ref);

Здесь state.collection создается автоматически и представляет собой объект, совместимый с useCollection.

  1. С useTreeState и useTree:
import {useTreeState} from '@react-stately/tree';
import {useTree} from '@react-aria/tree';

const state = useTreeState({items: treeItems});
const ref = React.useRef();

const {treeProps} = useTree({}, state, ref);

Внутри useTreeState также создается коллекция через useCollection, которая поддерживает вложенные элементы.


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

useCollection использует мемоизацию ключей и структур данных с индексами, что снижает количество перерендеров при изменении массива элементов. Рекомендуется:

  • Использовать уникальные и стабильные ключи для элементов.
  • Передавать однотипные объекты, чтобы React Aria мог эффективно сравнивать элементы.
  • Избегать пересоздания массивов при каждом рендере без необходимости.

Полезные методы и свойства

Метод/Свойство Назначение
getItem(key) Получение элемента по ключу
items Полный массив элементов коллекции
keys Массив ключей всех элементов
size Количество элементов в коллекции
map(fn) Перебор элементов с возвратом нового массива
forEach(fn) Перебор элементов без возврата массива
find(fn) Поиск первого элемента, удовлетворяющего условию

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

Фильтрация коллекции:

const filteredItems = collection.items.filter(item => item.name.includes('1'));

Построение списка компонентов React:

const listElements = collection.items.map(item => (
  <li key={item.key}>{item.name}</li>
));

Доступ к дочерним элементам дерева:

const parent = treeCollection.getItem('1');
parent.children.forEach(child => {
  console.log(child.key, child.name);
});

Резюме особенностей useCollection

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

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