Библиотека React Aria разделяет ответственность между
поведенческими хуками и хуками
состояния. Поведенческие хуки (useButton,
useMenu, useListBox и другие) обеспечивают
доступность, управление событиями и ARIA-атрибутами. Хуки состояния из
пакета @react-stately управляют данными, выбором,
навигацией, фокусом и изменениями состояния компонентов.
Такое разделение позволяет:
Хуки состояния реализуют модель, похожую на state machines, где каждое действие пользователя изменяет состояние структуры данных, а поведенческие хуки отражают эти изменения в DOM.
Система состояния React Aria реализована в пакете:
@react-stately
Основные категории хуков:
| Категория | Назначение |
|---|---|
| Коллекции | управление списками и элементами |
| Выбор | управление выделением элементов |
| Компоненты форм | состояние полей и вводов |
| Оверлеи | модальные окна, всплывающие элементы |
| Навигация | вкладки, меню, списки |
Часто используемые хуки:
useToggleStateuseOverlayTriggerStateuseListStateuseTreeStateuseSingleSelectListStateuseMultipleSelectionStateuseComboBoxStateuseMenuTriggerStateuseTabsStateuseToggleState управляет булевым
состоянием, которое может переключаться между true
и false.
Используется для:
import {useToggleState} from '@react-stately/toggle';
function ToggleExample() {
let state = useToggleState({
defaultSelected: false
});
return (
<button onCl ick={state.toggle}>
{state.isSelected ? "ON" : "OFF"}
</button>
);
}
| Свойство | Описание |
|---|---|
isSelected |
текущее состояние |
setSelected |
установка состояния |
toggle |
переключение |
useToggleState({
defaultSelected,
isSelected,
onChange
})
Начальное состояние.
defaultSelected: true
Контролируемый режим.
useToggleState({
isSelected: value,
onChange: setValue
});
function Switch({value, onChange}) {
let state = useToggleState({
isSelected: value,
onChange
});
return (
<button onCl ick={state.toggle}>
{state.isSelected ? "Enabled" : "Disabled"}
</button>
);
}
useOverlayTriggerState управляет состоянием
всплывающих элементов.
Используется для:
import {useOverlayTriggerState} from '@react-stately/overlays';
function ModalExample() {
let state = useOverlayTriggerState({});
return (
<>
<button onCl ick={state.open}>Open</button>
{state.isOpen && (
<div className="modal">
<button onCl ick={state.close}>Close</button>
</div>
)}
</>
);
}
| Свойство | Описание |
|---|---|
isOpen |
открыто ли окно |
open() |
открыть |
close() |
закрыть |
toggle() |
переключить |
useOverlayTriggerState({
defaultOpen,
isOpen,
onOpenChange
})
let state = useOverlayTriggerState({
isOpen,
onOpenChange: setOpen
});
useListState управляет коллекциями
элементов.
Используется для:
import {useListState} from '@react-stately/list';
function ListExample(props) {
let state = useListState(props);
return (
<ul>
{[...state.collection].map(item => (
<li key={item.key}>
{item.rendered}
</li>
))}
</ul>
);
}
Каждый элемент коллекции содержит:
Node
Свойства:
| Свойство | Описание |
|---|---|
key |
уникальный ключ |
rendered |
отображаемый контент |
value |
исходные данные |
type |
тип узла |
useListState принимает свойства:
{
items,
children,
selectionMode
}
const items = [
{id: 1, name: "Apple"},
{id: 2, name: "Orange"},
{id: 3, name: "Banana"}
];
function FruitList() {
let state = useListState({
items,
children: item => (
<Item key={item.id}>
{item.name}
</Item>
)
});
return (
<ul>
{[...state.collection].map(item => (
<li key={item.key}>
{item.rendered}
</li>
))}
</ul>
);
}
Управляет множественным выбором элементов.
Используется в:
import {useMultipleSelectionState} from '@react-stately/selection';
let state = useMultipleSelectionState({
selectionMode: "multiple"
});
| Свойство | Описание |
|---|---|
selectedKeys |
выбранные элементы |
setSelectedKeys |
установка выбора |
isSelected(key) |
проверка |
state.setSelectedKeys(new Set(["1", "2"]));
state.isSelected("1");
Используется для списков, где допустим один выбранный элемент.
Примеры:
import {useSingleSelectListState} from '@react-stately/list';
let state = useSingleSelectListState({
defaultSelectedKey: "1"
});
| Свойство | Описание |
|---|---|
selectedKey |
выбранный элемент |
setSelectedKey |
установка |
state.setSelectedKey("2");
Управляет состоянием комбинированного поля ввода с выбором.
Используется в:
import {useComboBoxState} fr om '@react-stately/combobox';
let state = useComboBoxState({
defaultFilter: contains,
items
});
| Свойство | Описание |
|---|---|
inputValue |
текст поля |
setInputValue |
изменить текст |
selectedKey |
выбранный элемент |
open() |
открыть список |
import {useFilter} from '@react-aria/i18n';
let {contains} = useFilter({sensitivity: 'base'});
Управляет состоянием меню.
Используется вместе с:
useMenuuseMenuTriggerimport {useMenuTriggerState} from '@react-stately/menu';
let state = useMenuTriggerState({});
| Метод | Описание |
|---|---|
open() |
открыть |
close() |
закрыть |
toggle() |
переключить |
function MenuExample() {
let state = useMenuTriggerState({});
return (
<>
<button onCl ick={state.toggle}>
Menu
</button>
{state.isOpen && (
<div className="menu">
Menu content
</div>
)}
</>
);
}
Управляет состоянием вкладок.
Используется вместе с:
useTabsuseTabListuseTabPanelimport {useTabsState} from '@react-stately/tabs';
let state = useTabsState({
defaultSelectedKey: "tab1"
});
| Свойство | Описание |
|---|---|
selectedKey |
активная вкладка |
setSelectedKey |
переключение |
state.setSelectedKey("tab2");
Состояние описывается декларативно.
useTabsState({
defaultSelectedKey: "tab1"
});
Один и тот же хук можно применять в разных компонентах интерфейса.
Поведенческие хуки React Aria автоматически используют состояние для:
Каждый хук поддерживает оба варианта.
Неконтролируемый:
defaultSelectedKey
defaultOpen
Контролируемый:
selectedKey
isOpen
onChange
Компоненты React Aria обычно состоят из двух уровней.
let state = useListState(props);
let {listBoxProps} = useListBox(props, state, ref);
function ListBox(props) {
let state = useListState(props);
let ref = React.useRef();
let {listBoxProps} = useListBox(props, state, ref);
return (
<ul {...listBoxProps} ref={ref}>
{[...state.collection].map(item => (
<Option key={item.key} item={item} state={state} />
))}
</ul>
);
}
Схема работы:
User Interaction
↓
React Aria behavior hook
↓
State hook update
↓
React render
↓
DOM update
Все компоненты списков используют единый интерфейс коллекций.
Одни и те же механизмы выбора работают для:
Состояние хранит:
Хуки автоматически поддерживают:
useListState
+
useListBox
useComboBoxState
+
useComboBox
useMenuTriggerState
+
useMenuTrigger
+
useMenu
useTabsState
+
useTabs
+
useTabList
+
useTab
Хуки состояния должны использоваться до рендеринга элементов.
Состояние должно хранить только:
Все изменения состояния происходят через методы хуков.
setSelectedKey
setSelectedKeys
toggle
open
close
Каждый элемент коллекции должен иметь уникальный key.
<Item key="id">
Хуки состояния React Aria обеспечивают:
Они формируют фундаментальную основу всей системы React Aria, позволяя строить сложные интерфейсы с полной поддержкой accessibility и управлением пользовательским взаимодействием на уровне абстракции состояния.