Валидация в реальном времени

React Aria предоставляет мощный набор хуков и утилит для построения доступных интерфейсов, включая эффективные механизмы валидации форм и полей ввода. Валидация в реальном времени — это процесс проверки данных на корректность по мере ввода пользователем, что улучшает UX и предотвращает накопление ошибок.

Использование useTextField для проверки ввода

Хук useTextField является базовым инструментом для работы с текстовыми полями. Он поддерживает атрибуты aria-invalid и aria-describedby, что позволяет динамически сигнализировать об ошибках:

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

function ValidatedInput({ label, validator }) {
  const [value, setValue] = useState('');
  const [error, setError] = useState(null);

  const { labelProps, inputProps } = useTextField({
    label,
    value,
    onChange: (val) => {
      setValue(val);
      const validationError = validator(val);
      setError(validationError);
    },
    'aria-invalid': !!error,
    'aria-describedby': error ? 'error-message' : undefined
  });

  return (
    <div>
      <label {...labelProps}>{label}</label>
      <input {...inputProps} />
      {error && <span id="error-message">{error}</span>}
    </div>
  );
}

Ключевые моменты:

  • aria-invalid принимает true, если значение поля не проходит валидацию.
  • aria-describedby связывает поле с сообщением об ошибке, что обеспечивает корректную озвучку экранными читалками.
  • Валидация вызывается при каждом изменении состояния поля (onChange), что позволяет реализовать проверку в реальном времени.

Хуки для комплексных форм: useForm и useFormField

Для организации сложных форм React Aria предоставляет useForm и useFormField. useFormField позволяет централизованно управлять состоянием ошибки и валидировать значения:

import { useForm, useFormField } from '@react-aria/form';
import { useState } from 'react';

function EmailField() {
  const [value, setValue] = useState('');
  const [error, setError] = useState(null);

  const { fieldProps, errorMessageProps } = useFormField({
    label: 'Email',
    validationState: error ? 'invalid' : 'valid',
    description: error
  });

  const validateEmail = (val) => {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return regex.test(val) ? null : 'Некорректный email';
  };

  return (
    <div>
      <label {...fieldProps}>{fieldProps.label}</label>
      <input
        {...fieldProps}
        value={value}
        onCha nge={(e) => {
          setValue(e.target.value);
          setError(validateEmail(e.target.value));
        }}
      />
      {error && <span {...errorMessageProps}>{error}</span>}
    </div>
  );
}

Особенности реализации:

  • validationState принимает значения valid или invalid, что автоматически корректно выставляет aria-invalid.
  • description можно использовать для передачи динамического сообщения об ошибке.
  • Реализация централизованной валидации позволяет подключать кастомные функции проверки для любых типов данных.

Интеграция с кастомными компонентами

React Aria позволяет создавать собственные компоненты с поддержкой доступности и валидации. Например, для селектов, чекбоксов или радиокнопок можно использовать хук useFormField для управления состоянием ошибки и озвучивания ошибок экранными читалками.

function CheckboxField({ label, required }) {
  const [checked, setChecked] = useState(false);
  const [error, setError] = useState(null);

  const { fieldProps, errorMessageProps } = useFormField({
    label,
    validationState: error ? 'invalid' : 'valid',
    description: error
  });

  const validate = (val) => (required && !val ? 'Обязательное поле' : null);

  return (
    <div>
      <label>
        <input
          type="checkbox"
          {...fieldProps}
          checked={checked}
          onCha nge={(e) => {
            setChecked(e.target.checked);
            setError(validate(e.target.checked));
          }}
        />
        {label}
      </label>
      {error && <span {...errorMessageProps}>{error}</span>}
    </div>
  );
}

Преимущества:

  • Полная совместимость с ARIA-атрибутами.
  • Возможность динамической проверки условий (например, обязательные поля, минимальные значения, форматы данных).
  • Валидация в реальном времени без внешних библиотек.

Подход к комплексной валидации

Для форм с множеством полей и зависимостями между ними рекомендуется:

  1. Создать объект состояния формы, где каждое поле хранит текущее значение и ошибку.
  2. Для каждого поля использовать useFormField для управления ARIA-атрибутами.
  3. Вызов функций валидации при onChange и onBlur, чтобы обрабатывать как мгновенную, так и окончательную проверку.
  4. Использовать централизованную функцию validateForm, чтобы проверять взаимозависимые поля.

Оптимизация производительности

  • Валидация в реальном времени может быть ресурсозатратной при сложных вычислениях. Для снижения нагрузки можно использовать дебаунсинг ввода.
  • React Aria хорошо сочетается с useEffect и useMemo для мемоизации результатов валидации, предотвращая лишние перерендеры.

Поддержка мультиязычности и кастомных сообщений

React Aria не ограничивает текст сообщений об ошибках. Можно подключать i18n-библиотеки, например react-intl, и передавать локализованные строки в description или errorMessageProps, сохраняя доступность для всех пользователей.


Валидация в реальном времени с React Aria позволяет строить динамичные и доступные интерфейсы без ущерба для UX, поддерживая все ключевые стандарты доступности.