React Aria — это библиотека, предоставляющая набор хуков для реализации доступных интерфейсов в React. Один из ключевых принципов работы с React Aria — чёткое разделение логики поведения компонента и его визуального представления. Это позволяет создавать компоненты, которые одновременно доступны, гибко настраиваются и легко тестируются.
React Aria предоставляет хуки, которые инкапсулируют всю поведенческую логику. Примеры таких хуков:
useButton — управление кнопками, включая обработку
клавиатуры и доступных атрибутов (aria-pressed,
disabled и т.д.).useCheckbox — логика для чекбоксов с поддержкой
indeterminate состояния.useDialog — управление открытием и закрытием диалоговых
окон с правильным фокусом.useMenu и useMenuItem — поведение
выпадающих меню и элементов меню.Эти хуки не задают разметку и не накладывают стили. Они возвращают набор props и состояний, которые затем можно передать любому JSX-элементу.
Пример использования useButton:
import { useButton } from '@react-aria/button';
import { useRef } from 'react';
function AccessibleButton(props) {
let ref = useRef();
let { buttonProps } = useButton(props, ref);
return <button {...buttonProps} ref={ref}>{props.children}</button>;
}
Здесь весь механизм обработки событий и доступности вынесен в
useButton, а компонент отвечает только за визуальное
представление.
React Aria не занимается управлением состояния компонентов напрямую. Для этого используется библиотека React Stately, которая предоставляет хуки для хранения состояния, синхронизации с UI и управления сложными сценариями:
useCheckboxState — состояние для чекбоксов.useRadioGroupState — логика для радиогрупп.useMenuTriggerState — управление открытием и закрытием
меню.useListState — состояние списков и их элементов.Пример комбинации React Aria и React Stately:
import { useCheckbox } from '@react-aria/checkbox';
import { useCheckboxState } from '@react-stately/checkbox';
import { useRef } from 'react';
function Checkbox({ children }) {
let state = useCheckboxState();
let ref = useRef();
let { inputProps } = useCheckbox({ children }, state, ref);
return (
<label>
<input {...inputProps} ref={ref} />
{children}
</label>
);
}
Здесь useCheckboxState управляет состоянием чекбокса, а
useCheckbox предоставляет доступные props для элемента
<input>.
Разделение логики и представления подразумевает, что визуальная часть компонента не зависит от состояния напрямую. Компоненты представления получают состояние и props от логических хуков и рендерят их соответствующим образом.
Пример:
function ButtonView({ children, buttonProps }) {
return <button {...buttonProps}>{children}</button>;
}
function Button({ children }) {
let ref = useRef();
let { buttonProps } = useButton({ onPress: () => alert('Clicked') }, ref);
return <ButtonView buttonProps={buttonProps}>{children}</ButtonView>;
}
Такой подход делает компонент универсальным: можно менять стили или оборачивать его в другие UI-библиотеки, не трогая логику доступности.
React Aria активно использует концепцию коллекций и фокусного управления. Все элементы списков, меню или таблиц управляются через хуки, которые обеспечивают:
Пример с меню:
import { useMenu, useMenuItem } from '@react-aria/menu';
import { useMenuTriggerState } from '@react-stately/menu';
import { useRef } from 'react';
function MenuButton() {
let state = useMenuTriggerState({});
let ref = useRef();
let { menuTriggerProps, menuProps } = useMenuTrigger({}, state, ref);
return (
<>
<button {...menuTriggerProps} ref={ref}>Open Menu</button>
{state.isOpen && <Menu {...menuProps} />}
</>
);
}
function Menu({ menuProps }) {
let ref = useRef();
let { menuProps: ariaMenuProps } = useMenu({}, { items: ['Item 1', 'Item 2'] }, ref);
return (
<ul {...ariaMenuProps} ref={ref}>
<MenuItem>Item 1</MenuItem>
<MenuItem>Item 2</MenuItem>
</ul>
);
}
function MenuItem({ children }) {
let ref = useRef();
let { menuItemProps } = useMenuItem({ key: children }, {}, ref);
return <li {...menuItemProps} ref={ref}>{children}</li>;
}
Здесь фокус и поведение меню полностью отделены от разметки, что обеспечивает гибкость и соответствие стандартам доступности.
buttonProps, inputProps,
menuProps), передавать в компонент представления.Разделение логики и представления в React Aria создаёт устойчивую архитектуру компонентов, где изменения в UI не влияют на поведение, а любые улучшения доступности реализуются централизованно в хуках. Это подход, который формирует основу для создания масштабируемых, доступных и легко поддерживаемых интерфейсов.