React Aria предоставляет набор хуков и утилит для создания доступных интерфейсов. Ключевой принцип организации кода — разделение логики состояния и визуального представления. Вместо монолитных компонентов, где управление состоянием смешано с рендерингом, рекомендуется строить структуру:
Пример: для создания доступного селекта можно использовать хук
useSelect для управления открытием списка, выбранным
элементом и фокусом, а визуальный компонент SelectList
только рендерит список и обрабатывает визуальные состояния.
import { useSelect } from '@react-aria/sel ect';
import { useSelectState } fr om '@react-stately/sel ect';
function SelectContainer({ items }) {
const state = useSelectState({ items });
const ref = React.useRef();
const { labelProps, triggerProps, valueProps, menuProps } = useSelect({ label: 'Выберите опцию' }, state, ref);
return (
<SelectList
labelProps={labelProps}
triggerProps={triggerProps}
valueProps={valueProps}
menuProps={menuProps}
state={state}
ref={ref}
/>
);
}
React Aria предоставляет набор хуков, разделённых по категориям:
Фокус и клавиатура
useFocusRing — определяет, находится ли элемент в
фокусе, и автоматически применяет стили фокусировки.useKeyboard — управляет клавиатурными событиями,
обеспечивая стандартную навигацию (стрелки, Enter, Escape).Состояние выбора и управления данными
useSelect, useComboBox,
useListBox — создают управляемое состояние для списков и
выпадающих меню.useTreeState, useTableState — управляют
структурированными данными с поддержкой выделения и навигации.ARIA-атрибуты и роли
role="listbox", role="option") и атрибуты
(aria-selected, aria-expanded) для поддержания
доступности.Использование хуков повышает читаемость кода и снижает вероятность ошибок при ручном управлении ARIA-атрибутами.
React Aria строит архитектуру таким образом, что состояние компонентов не зависит от их визуального представления. Это позволяет создавать сложные интерфейсы, изменяя только презентационную часть без переписывания логики:
function CustomSelect({ state, triggerProps, menuProps }) {
return (
<div>
<button {...triggerProps}>{state.selectedItem?.name || 'Выберите'}</button>
{state.isOpen && (
<ul {...menuProps}>
{state.collection.map(item => (
<li key={item.key}>{item.rendered}</li>
))}
</ul>
)}
</div>
);
}
Такой подход позволяет переиспользовать один и тот же хук состояния с различными визуальными компонентами: модальными окнами, dropdown-меню, кастомными таблицами.
React Aria часто используют вместе с библиотекой React Stately, которая предоставляет хуки управления состоянием. Принцип работы:
Пример: управляемый чекбокс:
import { useCheckbox } fr om '@react-aria/checkbox';
import { useCheckboxState } from '@react-stately/checkbox';
function Checkbox({ label }) {
const state = useCheckboxState({ defaultSelected: false });
const ref = React.useRef();
const { inputProps } = useCheckbox({ children: label }, state, ref);
return (
<label>
<input {...inputProps} ref={ref} />
{label}
</label>
);
}
Правильная организация кода в React Aria строится на следующих принципах:
props и ref для связи состояния и
разметки.Эта структура облегчает тестирование, масштабирование и поддержку приложения, позволяя добавлять новые интерфейсные элементы без пересмотра существующей логики.
В больших приложениях рекомендуется использовать React Context для передачи состояния между компонентами, которые не находятся в прямой иерархии. Пример — глобальный менеджер фокуса для модальных окон:
const FocusContext = React.createContext();
function FocusProvider({ children }) {
const [currentFocus, setCurrentFocus] = React.useState(null);
return (
<FocusContext.Provider value={{ currentFocus, setCurrentFocus }}>
{children}
</FocusContext.Provider>
);
}
function useFocusManager() {
return React.useContext(FocusContext);
}
В сочетании с хуками React Aria это позволяет управлять фокусом и навигацией на уровне всего приложения.
Для крупных проектов рекомендуется следующая структура:
/components
/Select
SelectContainer.js // логика состояния
SelectList.js // визуальное отображение
/Checkbox
CheckboxContainer.js
CheckboxUI.js
/hooks
useCustomFocus.js
useFilteredList.js
/utils
ariaUtils.js
stateHelpers.js
Такое разделение облегчает поддержку, тестирование и масштабирование компонентов, особенно когда проект использует React Aria для сложных интерфейсов с множеством интерактивных элементов.
Композиция компонентов позволяет создавать новые интерфейсы без дублирования логики:
function FilterableSelect({ items }) {
const state = useSelectState({ items });
const ref = React.useRef();
const { triggerProps, menuProps } = useSelect({ label: 'Фильтруемый селект' }, state, ref);
return (
<div>
<SearchInput state={state} />
<SelectList state={state} triggerProps={triggerProps} menuProps={menuProps} ref={ref} />
</div>
);
}
Здесь SearchInput и SelectList могут быть
использованы отдельно в других частях приложения, повторно используя
один и тот же хук состояния.