React Aria предоставляет набор хуков и утилит, ориентированных на доступность, которые помогают строить интерфейсы с корректной обработкой состояния ошибок. Важно понимать, что ошибки могут возникать как на уровне пользовательского ввода, так и на уровне логики компонента, и подход к их обработке должен быть системным.
useFormField для состояния ошибокХук useFormField позволяет управлять состоянием поля
формы, включая ошибки валидации. Он возвращает объект с основными
атрибутами:
import {useFormField} from '@react-aria/form';
function TextInput({label, error}) {
let {labelProps, inputProps, descriptionProps, errorMessageProps} = useFormField({
label,
error
});
return (
<div>
<label {...labelProps}>{label}</label>
<input {...inputProps} />
{error && <span {...errorMessageProps}>{error}</span>}
</div>
);
}
Ключевые моменты:
error — строка с сообщением об ошибке; если она есть,
React Aria автоматически связывает её с полем через
aria-describedby.errorMessageProps включает необходимые ARIA-атрибуты
для корректного чтения экранными читалками.В компонентах с асинхронной загрузкой данных ошибки часто связаны с сетевыми запросами. React Aria не занимается непосредственно обработкой промисов, но предоставляет подходы для связывания состояния ошибки с UI.
Пример с асинхронной валидацией:
import {useAsyncList} from '@react-stately/data';
function UserList() {
let list = useAsyncList({
async load({signal}) {
try {
let res = await fetch('/api/users', {signal});
if (!res.ok) throw new Error('Ошибка загрузки пользователей');
return {items: await res.json()};
} catch (err) {
return {items: [], error: err.message};
}
}
});
return (
<div>
{list.error ? <div role="alert">{list.error}</div> : null}
{list.items.map(user => <div key={user.id}>{user.name}</div>)}
</div>
);
}
role="alert" обеспечивает моментальное оповещение
пользователя о возникшей ошибке.list.error перед рендером
элементов списка, чтобы избежать некорректного состояния UI.Для компонентов управления, таких как селекты и чекбоксы, React Aria
предоставляет хуки useComboBox и
useCheckboxGroup. Ошибки здесь часто связаны с неправильным
состоянием или ограничениями ввода. Например:
import {useComboBox} from '@react-aria/combobox';
import {useState} from 'react';
function CountrySelect({countries}) {
let [value, setValue] = useState('');
let [error, setError] = useState('');
let {inputProps, listBoxProps} = useComboBox({
label: 'Выберите страну',
items: countries,
selectedKey: value,
onSelectionChange: key => {
if (!countries.includes(key)) setError('Неверная страна');
else setError('');
setValue(key);
}
});
return (
<div>
<input {...inputProps} />
{error && <span role="alert">{error}</span>}
</div>
);
}
Особенности:
role="alert".React Aria допускает интеграцию с любыми схемами валидации, например
с yup или zod. Главная задача — передавать
результат валидации через error или напрямую в
ARIA-атрибуты:
import * as yup from 'yup';
import {useFormField} from '@react-aria/form';
const schema = yup.object({
email: yup.string().email('Некорректный email').required('Обязательное поле')
});
function EmailInput({value, onChange}) {
let [error, setError] = useState('');
let {inputProps, errorMessageProps} = useFormField({label: 'Email', error});
const validate = async (val) => {
try {
await schema.validate({email: val});
setError('');
} catch (err) {
setError(err.message);
}
};
return (
<div>
<input
{...inputProps}
value={value}
onCha nge={(e) => {
onChange(e.target.value);
validate(e.target.value);
}}
/>
{error && <span {...errorMessageProps}>{error}</span>}
</div>
);
}
Преимущества такого подхода:
useFormField.role="alert" для критических ошибок,
которые нужно немедленно донести до пользователя.aria-describedby.useFormField или через локальное состояние с реактивным
обновлением ошибки.Этот подход обеспечивает системное управление ошибками и одновременно сохраняет доступность интерфейса, что является основной целью React Aria.