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

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

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

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

Архитектура компонентов времени в React Aria

Компоненты ввода времени в React Aria построены на разделении логики и представления. Основные элементы архитектуры:

React Aria Hooks

Обеспечивают доступность, обработку взаимодействия и передачу ARIA-атрибутов.

React Stately

Управляет состоянием значения времени, сегментами ввода и состоянием валидации.

DateValue / TimeValue

Типы данных из пакета @internationalized/date, используемые для хранения времени независимо от часовых поясов.

Пример используемых зависимостей:

import {useTimeField} from 'react-aria';
import {useTimeFieldState} from 'react-stately';
import {Time} from '@internationalized/date';

Состояние компонента содержит:

  • текущее значение времени
  • состояние редактирования сегментов
  • информацию о валидности
  • текст ошибки

Механизм встроенной валидации

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

Ключевые параметры:

Свойство Назначение
minValue минимально допустимое время
maxValue максимально допустимое время
isRequired обязательность поля
validate пользовательская функция проверки
validationState явное состояние валидности

Система автоматически отслеживает изменения значения и проверяет соответствие заданным ограничениям.

Ограничение диапазона времени

Одним из наиболее распространённых видов проверки является ограничение диапазона.

В интерфейсах часто необходимо:

  • ограничить рабочие часы
  • запретить выбор времени до текущего момента
  • задать временной интервал для записи

Пример настройки диапазона:

let state = useTimeFieldState({
  minValue: new Time(9, 0),
  maxValue: new Time(18, 0)
});

В этом случае пользователь может вводить значения только между 09:00 и 18:00.

При попытке выйти за пределы диапазона состояние компонента становится невалидным.

Проверка обязательного значения

Если поле времени должно быть заполнено, используется свойство isRequired.

let state = useTimeFieldState({
  isRequired: true
});

Особенности поведения:

  • пустое значение считается невалидным
  • браузер получает атрибут required
  • React Aria добавляет aria-required="true"

Это обеспечивает совместимость со стандартными HTML-формами и средствами доступности.

Пользовательская функция валидации

Бизнес-логика часто требует более сложных проверок, которые невозможно выразить через диапазоны.

Для этого используется свойство validate.

Функция получает текущее значение времени и возвращает текст ошибки.

let state = useTimeFieldState({
  validate(value) {
    if (value && value.hour < 12) {
      return "Время должно быть после полудня";
    }
  }
});

Особенности пользовательской проверки:

  • выполняется после встроенной валидации
  • может возвращать строку ошибки
  • может возвращать null, если ошибок нет

Сообщение автоматически связывается с полем через ARIA-атрибуты.

Состояние валидации

React Aria предоставляет три основных состояния:

Состояние Описание
valid значение корректно
invalid обнаружена ошибка
pending состояние проверки

В интерфейсе состояние передаётся через свойство validationState.

validationState="invalid"

Компонент автоматически добавляет:

  • aria-invalid
  • сообщение об ошибке
  • стилизацию

Отображение сообщений об ошибке

Сообщение об ошибке связывается с элементом ввода через aria-describedby.

Это позволяет экранным дикторам корректно объявлять проблему пользователю.

Пример структуры компонента:

<div>
  <TimeField />
  <span id="error-message">
    Неверное время
  </span>
</div>

React Aria автоматически связывает сообщение с элементом поля.

Валидация сегментов времени

Компоненты времени в React Aria используют сегментированный ввод.

Вместо одного текстового поля время разбивается на отдельные сегменты:

  • часы
  • минуты
  • секунды
  • AM/PM

Каждый сегмент валидируется отдельно.

Например:

  • часы: диапазон 0–23
  • минуты: диапазон 0–59
  • секунды: диапазон 0–59

Если пользователь вводит недопустимое значение, сегмент автоматически корректируется или отклоняется.

Проверка шага времени

В некоторых интерфейсах требуется ввод времени с фиксированным шагом.

Например:

  • каждые 15 минут
  • каждые 30 минут

В React Aria используется свойство granularity.

granularity="minute"

Дополнительно можно управлять шагом при помощи пользовательской логики.

Пример ограничения на интервалы 15 минут:

validate(value) {
  if (value.minute % 15 !== 0) {
    return "Время должно быть кратно 15 минутам";
  }
}

Реакция на изменение значения

Валидация тесно связана с обработкой событий изменения.

Основные события:

  • onChange
  • onBlur
  • onFocus

Пример:

function handleChange(time) {
  console.log(time);
}

После изменения значения:

  1. обновляется состояние
  2. запускается встроенная проверка
  3. выполняется пользовательская валидация
  4. обновляется состояние ошибки

Валидация в формах

React Aria позволяет интегрировать компоненты времени в стандартные HTML-формы.

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

  • передача значения через скрытый input
  • поддержка submit
  • работа с браузерной валидацией

Пример:

<form>
  <TimeField name="appointmentTime" />
</form>

При отправке формы значение автоматически сериализуется.

Асинхронная валидация

Иногда требуется проверка времени на стороне сервера.

Примеры:

  • проверка доступности слота записи
  • проверка пересечения бронирований

Для таких случаев используется асинхронная логика внутри onChange.

async function validateTime(time) {
  let available = await checkTime(time);

  if (!available) {
    setError("Время занято");
  }
}

Асинхронная проверка обычно сопровождается состоянием pending.

Связанные поля времени

Многие формы используют диапазон времени:

  • начало события
  • конец события

Валидация должна учитывать связь между полями.

Пример проверки:

validate(value) {
  if (value.compare(endTime) > 0) {
    return "Начало не может быть позже окончания";
  }
}

Для второго поля выполняется зеркальная проверка.

Обработка часовых поясов

В React Aria значения времени представлены через объекты Time.

Они не привязаны к часовому поясу, что упрощает валидацию.

Однако при работе с датами используется тип ZonedDateTime, где проверки могут учитывать:

  • смещение часового пояса
  • переходы на летнее время

Валидация времени в таких случаях выполняется после преобразования к нужной зоне.

Контроль ошибок через состояние

Иногда приложение должно управлять состоянием ошибок вручную.

Пример:

let [error, setError] = useState(null);

<TimeField
  validationState={error ? "invalid" : "valid"}
  errorMessage={error}
/>

Такой подход используется при сложной бизнес-логике или серверной проверке.

Доступность при валидации

React Aria автоматически реализует рекомендации WAI-ARIA.

При ошибке добавляются:

  • aria-invalid="true"
  • aria-describedby
  • объявления через screen reader

Сообщения об ошибках становятся частью доступного описания элемента.

Это обеспечивает корректное восприятие интерфейса пользователями вспомогательных технологий.

Практические сценарии валидации времени

Наиболее распространённые сценарии:

Рабочие часы

Проверка диапазона:

09:00 — 18:00

Бронирование

Проверка доступности временного слота.

Интервалы

Проверка кратности:

каждые 30 минут

Связанные поля

Проверка последовательности:

startTime < endTime

Минимальное время

Запрет выбора времени раньше текущего.

Производительность проверки

Валидация выполняется при каждом изменении значения.

Чтобы избежать лишних вычислений:

  • сложную логику выносят в мемоизированные функции
  • асинхронные проверки запускают с debounce
  • серверные запросы выполняют только после завершения ввода

Такая оптимизация особенно важна в формах с большим количеством временных полей.

Расширение системы валидации

React Aria допускает создание собственных компонентов поверх базовых хуков.

Валидация может быть вынесена в отдельный модуль:

function validateBusinessTime(time) {
  if (time.hour < 10) {
    return "Рабочий день начинается в 10:00";
  }
}

После этого функция используется во всех компонентах времени приложения.

Это обеспечивает:

  • единообразие правил
  • централизованное управление логикой
  • упрощение сопровождения кода.

Синхронизация с серверной моделью

При работе с API важно соблюдать единый формат времени.

Обычно используется:

  • ISO 8601
  • строки HH:mm:ss

Перед отправкой значение преобразуется:

time.toString()

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