useTextField для текстовых полей

useTextField — это хук из библиотеки React Aria, предназначенный для создания полностью доступных текстовых полей. Он обеспечивает правильную интеграцию с технологиями доступности (ARIA), управляет событиями фокуса и состояниями ввода, а также упрощает работу с атрибутами формы. Основная задача useTextField — гарантировать, что стандартное <input> или <textarea> ведёт себя корректно в любой среде, включая скринридеры и клавиатурную навигацию.


Импорт и базовая структура

Для начала необходимо импортировать хук:

import { useTextField } from '@react-aria/textfield';
import { useRef } from 'react';

Типичная структура текстового поля включает следующие шаги:

  1. Создание ссылки на элемент через useRef.
  2. Вызов useTextField с необходимыми параметрами.
  3. Распределение возвращаемых атрибутов между <label> и <input> или <textarea>.

Пример базового текстового поля:

function TextInput(props) {
  const ref = useRef();
  const { labelProps, inputProps } = useTextField(props, ref);

  return (
    <div>
      <label {...labelProps}>{props.label}</label>
      <input {...inputProps} ref={ref} />
    </div>
  );
}

Аргументы и параметры

useTextField принимает два основных аргумента: props и ref. Ключевые свойства props:

  • label — текст метки поля.
  • isDisabled — блокировка поля ввода.
  • isReadOnly — установка только для чтения.
  • isRequired — обязательность заполнения.
  • type — тип <input> (например, text, email, password).
  • placeholder — подсказка внутри поля.
  • value и onChange — управление состоянием контролируемого компонента.
  • autoFocus — автоматический фокус при рендере.

Передача ref необходима для корректного управления фокусом и связи с DOM.


Возвращаемые значения

useTextField возвращает объект с двумя ключевыми свойствами:

  1. labelProps — атрибуты для элемента <label>. Включает htmlFor и другие ARIA-атрибуты.

  2. inputProps — атрибуты для <input> или <textarea>. Содержит id, aria-required, aria-invalid, обработчики событий (onChange, onFocus, onBlur) и поддерживает все необходимые свойства для доступности.


Управление состояниями

Деактивированное и только для чтения

<input
  {...inputProps}
  ref={ref}
  disabled={props.isDisabled}
  readOnly={props.isReadOnly}
/>

При использовании isDisabled поле становится недоступным для взаимодействия, а isReadOnly позволяет просматривать, но не изменять значение.

Обязательное поле

Атрибут isRequired автоматически добавляет aria-required="true" и корректно взаимодействует со скринридерами:

<input {...inputProps} ref={ref} required={props.isRequired} />

Работа с ошибками валидации

useTextField поддерживает интеграцию с внешними системами валидации. Для передачи состояния ошибки используется свойство validationState:

const { labelProps, inputProps } = useTextField({
  label: "Email",
  validationState: "invalid"
}, ref);

Значения validationState:

  • "valid" — поле корректно.
  • "invalid" — поле содержит ошибку. Автоматически добавляет aria-invalid="true".

Поддержка <textarea>

useTextField работает не только с <input>, но и с <textarea>:

function TextArea(props) {
  const ref = useRef();
  const { labelProps, inputProps } = useTextField(props, ref);

  return (
    <div>
      <label {...labelProps}>{props.label}</label>
      <textarea {...inputProps} ref={ref} />
    </div>
  );
}

Все ARIA-атрибуты и события работают одинаково, что обеспечивает одинаковый уровень доступности для многострочных и однострочных полей.


Стилизация и кастомизация

useTextField не накладывает стили и не изменяет визуальное поведение. Стилизация полностью остаётся за разработчиком. Обычно используется комбинация CSS-модулей или Tailwind:

.input {
  border: 1px solid #ccc;
  padding: 8px;
  border-radius: 4px;
  font-size: 16px;
}

.input:focus {
  border-color: #3182ce;
  outline: none;
}
<input {...inputProps} ref={ref} className="input" />

Важно: любые кастомные атрибуты или события можно добавлять поверх inputProps, не нарушая доступность.


Интеграция с формами

useTextField легко комбинируется с библиотеками управления формами, такими как React Hook Form или Formik. Основная практика — использовать value и onChange для синхронизации состояния:

function ControlledInput({ control }) {
  const ref = useRef();
  const { labelProps, inputProps } = useTextField({
    label: "Username",
    value: control.value,
    onChange: control.onChange
  }, ref);

  return (
    <div>
      <label {...labelProps}>Username</label>
      <input {...inputProps} ref={ref} />
    </div>
  );
}

Дополнительные возможности

  • autoFocus — автоматически устанавливает фокус при монтировании компонента.
  • description и errorMessage — позволяют добавить дополнительные поясняющие тексты с правильными aria-describedby связями.
  • Поддержка локализации и динамических изменений состояния с полной сохранностью ARIA-атрибутов.

useTextField обеспечивает безопасную, доступную и стандартизированную реализацию текстовых полей в React-приложениях, оставляя полный контроль над внешним видом и интеграцией с формами.