React Aria — это набор хуков для создания доступных компонентов пользовательского интерфейса в React. Он не предоставляет готовых визуальных компонентов, а фокусируется на управлении поведением, состоянием и доступностью, что позволяет расширять функциональность стандартных элементов и создавать собственные UI-компоненты с полной поддержкой ARIA.
В основе React Aria лежит концепция разделения состояния и рендеринга. Это позволяет создавать обёртки вокруг базовых HTML-элементов или сторонних компонентов, добавляя доступные взаимодействия.
Пример: использование хука useButton для кастомной
кнопки.
import {useButton} from '@react-aria/button';
import {useRef} from 'react';
function CustomButton(props) {
const ref = useRef();
const {buttonProps} = useButton(props, ref);
return (
<button {...buttonProps} ref={ref} style={{padding: '10px', fontSize: '16px'}}>
{props.children}
</button>
);
}
Ключевые моменты:
useButton обеспечивает корректную обработку клавиатуры,
фокуса и ARIA-атрибутов.pressed, disabled)
синхронизируется с DOM без необходимости вручную писать обработчики
событий.React Aria предоставляет хуки для сложных UI-компонентов: селектов, чекбоксов, табов, модальных окон, тултипов и т.д. Эти хуки берут на себя:
Пример расширения стандартного селекта через
useSelect:
import {useSelect} from '@react-aria/sel ect';
import {useState, useRef} fr om 'react';
function CustomSelect({items}) {
const [selectedKey, setSelectedKey] = useState(null);
const ref = useRef();
const {labelProps, triggerProps, valueProps, menuProps} = useSelect(
{items, selectedKey, onSelectionChange: setSelectedKey},
ref
);
return (
<div>
<label {...labelProps}>Выберите элемент:</label>
<button {...triggerProps} ref={ref}>
{selectedKey || 'Ничего не выбрано'}
</button>
<ul {...menuProps}>
{items.map(item => (
<li key={item.key}>{item.name}</li>
))}
</ul>
</div>
);
}
Особенности расширения:
React Aria активно использует хуки useFocus,
useHover, usePress для управления
интерактивными состояниями:
useFocus отслеживает фокус и позволяет динамически
менять стили.useHover регистрирует наведение мыши, обеспечивая
визуальную обратную связь.usePress объединяет события клика, касания и клавиатуры
в единый API.Пример сочетания хуков для интерактивного элемента:
import {useFocus, useHover, usePress} from '@react-aria/interactions';
import {useRef, useState} from 'react';
function InteractiveBox() {
const ref = useRef();
const [isFocused, setFocused] = useState(false);
const [isHovered, setHovered] = useState(false);
const {focusProps} = useFocus({onFocusChange: setFocused});
const {hoverProps} = useHover({onHoverChange: setHovered});
const {pressProps} = usePress({onPress: () => alert('Нажато!')});
const style = {
width: '150px',
height: '150px',
backgroundColor: isFocused ? 'blue' : isHovered ? 'lightblue' : 'grey',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
cursor: 'pointer',
userSelect: 'none'
};
return <div {...focusProps} {...hoverProps} {...pressProps} ref={ref} style={style}>Нажми меня</div>;
}
Преимущества:
Использование useOverlay и useDialog
позволяет расширять стандартные модальные окна с поддержкой
доступности:
import {useOverlay, useDialog} from '@react-aria/overlays';
import {useRef} from 'react';
function CustomModal({isOpen, onClose, children}) {
const ref = useRef();
const {overlayProps} = useOverlay({isOpen, onClose, isDismissable: true}, ref);
const {dialogProps, titleProps} = useDialog({}, ref);
if (!isOpen) return null;
return (
<div {...overlayProps} style={{position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.3)'}}>
<div {...dialogProps} ref={ref} style={{background: 'white', padding: '20px', margin: '50px auto', width: '300px'}}>
<h2 {...titleProps}>Заголовок модального окна</h2>
{children}
<button onCl ick={onClose}>Закрыть</button>
</div>
</div>
);
}
Расширение функциональности модальных окон:
React Aria учитывает локализацию и направления текста (LTR/RTL).
Например, useDatePicker автоматически подстраивает
календарь под региональные настройки. Это позволяет расширять
стандартные компоненты без переписывания логики работы с датами и
форматами.
Ключевой принцип расширения функциональности — композиция
хуков. Один компонент может объединять useButton,
useFocus, useHover и useOverlay,
создавая уникальный, доступный UI:
Эта стратегия позволяет создавать масштабируемые, доступные и полностью настраиваемые компоненты, расширяя стандартные возможности React без потери производительности и UX.