Библиотека React Aria предоставляет готовые хуки и утилиты для управления доступностью и поведением интерфейсных компонентов, а React Hook Form облегчает работу с формами в React, обеспечивая простое управление состоянием, валидацией и производительностью. Совмещение этих библиотек позволяет создавать полностью доступные формы с минимальным количеством повторяющегося кода.
Для работы необходимо установить обе библиотеки:
npm install @react-aria/aria @react-aria/button @react-aria/checkbox react-hook-form
Основные пакеты React Aria, которые будут использоваться при работе с формами:
useCheckbox – управление состоянием и доступностью
чекбоксов.useButton – корректное поведение кнопок с поддержкой
клавиатурной навигации.useTextField – обработка текстовых полей с учетом
ARIA-атрибутов.React Hook Form предоставляет:
useForm – основной хук для управления состоянием
формы.Controller – компонент для интеграции контролируемых
компонентов, таких как те, что предоставлены React Aria.Controller для компонентов React AriaReact Hook Form по умолчанию работает с неконтролируемыми элементами,
но компоненты React Aria часто требуют контролируемого состояния. Для
интеграции используется Controller:
import { useForm, Controller } from "react-hook-form";
import { useCheckbox } from "@react-aria/checkbox";
function AccessibleCheckbox({ label, control, name }) {
return (
<Controller
control={control}
name={name}
render={({ field }) => {
let { inputProps } = useCheckbox(field);
return (
<label>
<input {...inputProps} />
{label}
</label>
);
}}
/>
);
}
Ключевые моменты:
useCheckbox возвращает inputProps, которые
обеспечивают правильную доступность (ARIA-атрибуты, обработка
клавиатуры).Controller передает field объект,
содержащий value, onChange и
onBlur, что позволяет синхронизировать состояние с React
Hook Form.Для текстовых полей используется useTextField:
import { useTextField } from "@react-aria/textfield";
function AccessibleInput({ label, control, name }) {
return (
<Controller
control={control}
name={name}
render={({ field }) => {
let { inputProps, labelProps } = useTextField(field);
return (
<div>
<label {...labelProps}>{label}</label>
<input {...inputProps} />
</div>
);
}}
/>
);
}
Особенности:
labelProps гарантируют, что метка корректно связана с
полем.inputProps включают ARIA-атрибуты, обработчики фокуса и
состояния ошибки, если они переданы.useButton позволяет добавить кнопке полную поддержку
клавиатуры и ARIA:
import { useButton } from "@react-aria/button";
function SubmitButton({ children, onPress }) {
let ref = React.useRef();
let { buttonProps } = useButton({ onPress }, ref);
return (
<button {...buttonProps} ref={ref}>
{children}
</button>
);
}
Использование с формой:
function Form() {
const { handleSubmit } = useForm();
const onSub mit = data => console.log(data);
return (
<form onSub mit={handleSubmit(onSubmit)}>
<AccessibleInput name="username" label="Имя пользователя" control={control} />
<AccessibleCheckbox name="agree" label="Согласие" control={control} />
<SubmitButton>Отправить</SubmitButton>
</form>
);
}
React Hook Form позволяет легко добавлять правила валидации, а React Aria помогает отображать ошибки с корректными ARIA-атрибутами:
<Controller
control={control}
name="email"
rules={{ required: "Email обязателен", pattern: { value: /^\S+@\S+$/i, message: "Некорректный email" } }}
render={({ field, fieldState }) => {
let { inputProps, labelProps } = useTextField(field);
return (
<div>
<label {...labelProps}>Email</label>
<input {...inputProps} />
{fieldState.error && <span role="alert">{fieldState.error.message}</span>}
</div>
);
}}
/>
Принципы:
fieldState.error содержит сообщение об ошибке, которое
автоматически обновляется при изменении значения.role="alert" позволяет экранным читалкам
уведомлять пользователя о ошибке.React Aria предоставляет хуки для управления фокусом
(useFocusRing, useFocus) и взаимодействием с
клавиатурой. Это особенно важно для форм с динамическими элементами:
import { useFocusRing } from "@react-aria/focus";
function FocusableInput({ label, control, name }) {
return (
<Controller
control={control}
name={name}
render={({ field }) => {
let { inputProps } = useTextField(field);
let { isFocusVisible, focusProps } = useFocusRing();
return (
<div>
<label>{label}</label>
<input {...inputProps} {...focusProps} style={{ outline: isFocusVisible ? "2px solid blue" : "none" }} />
</div>
);
}}
/>
);
}
Эффекты:
Controller только там, где это
необходимо. Неконтролируемые поля через register
более производительны.useState
внутри компонентов.Комбинация React Aria и React Hook Form позволяет создавать формы с:
Такой подход особенно полезен для сложных интерфейсов с динамическими и интерактивными элементами, где важно сочетать доступность, UX и чистоту архитектуры кода.