React Aria предоставляет набор хуков, которые обеспечивают доступность интерфейсов без привязки к конкретным визуальным компонентам. Центральным подходом является разделение логики состояния и представления. Вместо того чтобы создавать готовые визуальные компоненты, React Aria предоставляет паттерны композиции, которые позволяют комбинировать поведение и внешний вид по необходимости.
Каждый хук в React Aria возвращает объект с свойствами и
обработчиками событий, которые можно безопасно применять к
любым элементам DOM или кастомным компонентам. Например,
useButton не создаёт кнопку визуально, но возвращает
необходимые атрибуты и события для корректной работы:
import {useButton} from '@react-aria/button';
import {useRef} from 'react';
function CustomButton({onPress, children}) {
let ref = useRef();
let {buttonProps} = useButton({onPress}, ref);
return (
<button {...buttonProps} ref={ref}>
{children}
</button>
);
}
Ключевые моменты:
useButton добавляет правильные ARIA-атрибуты
(aria-pressed, role="button" и др.).onClick, onKeyDown)
автоматически настроены под доступность.React Aria активно использует концепцию render props для передачи состояния и обработчиков в визуальные компоненты. Это позволяет полностью контролировать разметку и стили:
import {useToggleButton} from '@react-aria/button';
function Toggle({children}) {
let ref = useRef();
let {toggleButtonProps, isSelected} = useToggleButton({onPress: () => {}}, ref);
return children({toggleButtonProps, isSelected, ref});
}
// Использование
<Toggle>
{({toggleButtonProps, isSelected, ref}) => (
<button {...toggleButtonProps} ref={ref}>
{isSelected ? 'Вкл' : 'Выкл'}
</button>
)}
</Toggle>
Преимущества паттерна:
isSelected) и
разметки.Для сложных интерфейсов можно комбинировать несколько хуков. Например, при создании комбинированного элемента меню с кнопкой и списком элементов используется составление хуков:
import {useMenu, useMenuItem} from '@react-aria/menu';
import {useListState} from '@react-stately/list';
import {useRef} from 'react';
function Menu({items}) {
let state = useListState({items});
let ref = useRef();
let {menuProps} = useMenu({}, state, ref);
return (
<ul {...menuProps} ref={ref}>
{[...state.collection].map(item => (
<MenuItem key={item.key} item={item} state={state} />
))}
</ul>
);
}
function MenuItem({item, state}) {
let ref = useRef();
let {menuItemProps} = useMenuItem({key: item.key}, state, ref);
return (
<li {...menuItemProps} ref={ref}>
{item.rendered}
</li>
);
}
Важные моменты:
useListState управляет состоянием списка
(selectedKeys, focusedKey).useMenu и useMenuItem добавляют
доступность и управление событиями.React Aria поддерживает концепцию слотов, когда
логика одного компонента делится между несколькими визуальными частями.
Например, useSlider предоставляет свойства для трека,
ползунка и меток:
import {useSlider} from '@react-aria/slider';
import {useSliderState} from '@react-stately/slider';
import {useRef} from 'react';
function Slider({value, onChange, min, max}) {
let state = useSliderState({value, onChange, min, max});
let ref = useRef();
let {trackProps, thumbProps} = useSlider({min, max}, state, ref);
return (
<div {...trackProps} ref={ref} className="track">
<div {...thumbProps} className="thumb" />
</div>
);
}
Преимущества:
Основная цель паттернов композиции — гарантировать доступность без наложения визуальных ограничений. Хуки React Aria заботятся о:
Паттерны композиции позволяют создавать модульные компоненты, которые можно:
Применение этих принципов делает интерфейсы гибкими, доступными и полностью контролируемыми с точки зрения состояния и событий.
useState, useListState,
useSliderState.Эти подходы формируют основу гибкого и масштабируемого интерфейсного кода на базе React Aria.