useTable для таблиц

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


Инициализация таблицы

Для начала работы с useTable необходимо импортировать его вместе с сопутствующими хуками и компонентами:

import { useTable, useTableState } from '@react-stately/table';
import { useTable as useTableAria } from '@react-aria/table';
import { useFocusRing } from '@react-aria/focus';

useTable работает в связке с state таблицы, который создается с помощью useTableState. State управляет данными, сортировкой и выделением строк.

const state = useTableState({
  columns: [
    { name: 'Имя', key: 'name' },
    { name: 'Возраст', key: 'age' },
    { name: 'Город', key: 'city' }
  ],
  items: [
    { id: '1', name: 'Иван', age: 30, city: 'Москва' },
    { id: '2', name: 'Анна', age: 25, city: 'Санкт-Петербург' }
  ]
});

После создания состояния вызывается useTableAria, который возвращает необходимые props для таблицы и её элементов.

const { tableProps, gridProps } = useTableAria({ /* props */ }, state);

Структура таблицы

Таблица состоит из следующих ключевых компонентов:

  • Table – контейнер таблицы, получает tableProps.
  • Row – строки таблицы, получают rowProps.
  • Cell / ColumnHeader – ячейки и заголовки, получают соответствующие props.

Пример рендеринга:

<table {...tableProps}>
  <thead>
    <tr>
      {state.collection.headerRows[0].childNodes.map(column => (
        <th key={column.key} {...column.props}>
          {column.rendered}
        </th>
      ))}
    </tr>
  </thead>
  <tbody>
    {state.collection.items.map(item => (
      <tr key={item.key} {...item.props}>
        {item.childNodes.map(cell => (
          <td key={cell.key} {...cell.props}>
            {cell.rendered}
          </td>
        ))}
      </tr>
    ))}
  </tbody>
</table>

Управление фокусом и выделением

React Aria предоставляет интеграцию с фокусом через useFocusRing. Это позволяет визуально выделять активную строку или ячейку.

const { isFocusVisible, focusProps } = useFocusRing();

<td {...cell.props} {...focusProps} className={isFocusVisible ? 'focused' : ''}>
  {cell.rendered}
</td>

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

const state = useTableState({
  selectionMode: 'multiple', // single, multiple, none
  columns: [...],
  items: [...]
});

Выделенные строки автоматически отслеживаются в state.selectionManager.


Сортировка и фильтрация

useTableState позволяет задавать сортировку по столбцам:

const state = useTableState({
  columns: [
    { name: 'Имя', key: 'name', allowsSorting: true },
    { name: 'Возраст', key: 'age', allowsSorting: true }
  ],
  items: [...],
  sortDescriptor: { column: 'name', direction: 'ascending' }
});

Для сортируемых заголовков следует использовать column.props с aria-sort, который автоматически управляется React Aria:

<th {...column.props} onCl ick={() => state.sort(column.key)}>
  {column.rendered}
</th>

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

useTable автоматически добавляет все необходимые ARIA атрибуты:

  • role="table" для контейнера
  • role="row" для строк
  • role="columnheader" и role="cell" для заголовков и ячеек
  • Поддержка aria-selected, aria-sort и aria-multiselectable

Это гарантирует корректное взаимодействие с экранными читалками и клавиатурной навигацией.


Интеграция с виртуализацией

Для больших таблиц рекомендуется использовать виртуализацию с react-virtual или аналогами. Важно передавать state.collection и props ячеек напрямую в виртуальные рендеры, чтобы сохранялись все ARIA-атрибуты и фокус.

<Virtualizer
  totalCount={state.collection.size}
  overscan={5}
  renderItem={(index) => {
    const item = state.collection.getItem(index);
    return (
      <tr key={item.key} {...item.props}>
        {item.childNodes.map(cell => (
          <td key={cell.key} {...cell.props}>{cell.rendered}</td>
        ))}
      </tr>
    );
  }}
/>

Кастомизация и стилизация

useTable предоставляет только логику и доступность, поэтому визуальное оформление полностью контролируется через CSS или сторонние UI-библиотеки. Важно сохранять:

  • Видимость фокуса
  • Состояния выделения строк
  • Анимацию сортировки (по желанию)

Пример базового CSS для выделенной строки:

tr[aria-selected="true"] {
  background-color: #e0f7fa;
}
td.focused {
  outline: 2px solid #0288d1;
}

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