Структура объекта errors

В связке react-hook-form и @hookform/resolvers/yup объект errors является центральным результатом валидации формы. Он формируется на основе ValidationError, который генерируется библиотекой Yup, и преобразуется резолвером в структуру, понятную механизму управления формой.

Базовая модель объекта errors

Объект errors представляет собой древовидную структуру, где ключи соответствуют именам полей формы, а значения — объектам описания ошибки.

Типовая форма:

errors = {
  email: {
    type: "required",
    message: "Email обязателен",
    ref: HTMLInputElement
  },
  profile: {
    firstName: {
      type: "min",
      message: "Слишком короткое имя",
      ref: HTMLInputElement
    }
  }
}

Ключевые характеристики:

  • Иерархичность — структура повторяет структуру формы
  • Рекурсивность — вложенные объекты ошибок для вложенных схем
  • Сопоставление по path — Yup использует путь a.b.c, который преобразуется в вложенные объекты

Источник структуры: Yup ValidationError

Yup генерирует объект ошибки следующего вида:

ValidationError {
  name: "ValidationError",
  message: "Invalid input",
  path: "profile.firstName",
  type: "min",
  inner: [...]
}

Ключевым элементом является массив inner, содержащий все ошибки при abortEarly: false:

inner: [
  {
    path: "email",
    message: "Email обязателен",
    type: "required"
  },
  {
    path: "profile.firstName",
    message: "Минимум 3 символа",
    type: "min"
  }
]

Резолвер преобразует этот массив в объект errors, группируя элементы по path.


Алгоритм преобразования Yup → errors

При работе yupResolver выполняется следующая логика:

  1. Выполняется schema.validate(data, { abortEarly: false })
  2. При наличии ошибок Yup формирует ValidationError
  3. Извлекается массив inner
  4. Каждый элемент inner маппится по path
  5. Формируется вложенный объект через разбиение пути по точке

Пример преобразования:

"path": "profile.firstName"

превращается в:

errors.profile.firstName

Структура узла ошибки

Каждое поле в errors содержит стандартизированный набор свойств.

type

Определяет тип нарушения валидации.

Примеры:

  • required
  • min
  • max
  • email
  • matches

Значение берётся напрямую из Yup-валидатора.


message

Человекочитаемое описание ошибки.

message: "Минимальная длина — 3 символа"

Формируется на уровне Yup через message в схеме.


ref

Ссылка на DOM-элемент поля формы.

Используется для:

  • установки фокуса
  • визуального выделения
  • интеграции с setFocus

Пример:

ref: HTMLInputElement

root (в некоторых конфигурациях)

Используется для хранения глобальных ошибок формы, не привязанных к конкретному полю.

errors.root = {
  message: "Ошибка сервера",
  type: "server"
}

types (множественные ошибки)

При использовании criteriaMode: "all" возможно наличие нескольких ошибок для одного поля.

errors.password = {
  types: {
    min: "Минимум 8 символов",
    matches: "Должен содержать цифру"
  },
  message: "Некорректный пароль"
}

Особенности:

  • types содержит список всех нарушенных правил
  • message обычно хранит первую или агрегированную ошибку

Вложенные структуры объектов

Yup поддерживает сложные схемы, включая объекты и массивы. Это напрямую отражается в errors.

Вложенные объекты

Схема:

{
  profile: yup.object({
    name: yup.string().required(),
    age: yup.number().min(18)
  })
}

Результат:

errors.profile.name.message
errors.profile.age.message

Массивы

Для массивов используется индексная адресация:

Схема:

users: yup.array().of(
  yup.object({
    email: yup.string().required()
  })
)

Ошибки:

errors.users[0].email.message
errors.users[1].email.message

Особенности:

  • индексы сохраняются как числовые ключи
  • структура динамически расширяется под данные формы

Поведение при abortEarly: false

При отключённом раннем завершении Yup собирает все ошибки:

schema.validate(data, { abortEarly: false })

В этом режиме:

  • формируется полный массив inner
  • в errors попадает каждая ошибка поля
  • возможно наличие нескольких ошибок на одно поле (при criteriaMode: "all")

Поведение при abortEarly: true

Если включено раннее завершение:

  • Yup возвращает только первую ошибку
  • inner может быть пустым или содержать один элемент
  • errors содержит минимальное количество данных

Это влияет на полноту объекта:

errors = {
  email: {
    type: "required",
    message: "Обязательное поле"
  }
}

Нормализация путей ошибок

Резолвер выполняет преобразование путей:

Yup path errors structure
user.name errors.user.name
items[0].title errors.items[0].title
a.b.c errors.a.b.c

Правила:

  • точки → вложенные объекты
  • квадратные скобки → массивы
  • строки пути разбиваются на сегменты

Конфликты и перезапись ошибок

При наличии нескольких ошибок одного поля:

  • последняя обработанная ошибка может перезаписать предыдущую
  • либо формируется types, если включён criteriaMode: "all"

Пример:

errors.password = {
  type: "min",
  message: "Слишком короткий пароль"
}

или

errors.password = {
  types: {
    min: "Слишком короткий",
    max: "Слишком длинный"
  }
}

Связь errors и состояния формы

Объект errors интегрирован в жизненный цикл формы:

  • формируется при handleSubmit
  • обновляется при trigger
  • очищается при изменении значения поля
  • синхронизируется с режимами mode: "onChange" | "onBlur"

Глубокие вложенные ошибки и их особенности

При сложных схемах возникают особенности:

1. Пропущенные промежуточные узлы

Если ошибка возникает в a.b.c, промежуточные узлы создаются автоматически:

errors.a.b.c

при этом a и b могут быть пустыми объектами без message.


2. Смешанные типы данных

При конфликте структуры формы и схемы:

  • объект может стать массивом
  • массив может интерпретироваться как объект с индексами

Это влияет на интерпретацию errors.


3. Динамические поля

При использовании useFieldArray структура errors изменяется динамически:

  • удалённые элементы исчезают из errors
  • новые элементы получают собственные узлы

Роль Yup в формировании type и message

Yup позволяет задавать кастомные сообщения:

yup.string().required("Поле обязательно")

Эти сообщения напрямую попадают в:

errors.field.message

Тип ошибки берётся из валидатора:

  • required
  • min
  • max

Сводная структура узла errors

Единичный узел ошибки может включать:

{
  type: string,
  message: string,
  ref: HTMLElement,
  types?: Record<string, string>,
  root?: {
    message: string,
    type: string
  }
}

Поведение при частичной валидации

При валидации отдельных полей через trigger("field"):

  • обновляется только соответствующий узел
  • остальные ошибки сохраняются
  • структура errors остаётся стабильной

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

Объект errors не предназначен для сериализации:

  • содержит DOM-ссылки (ref)
  • содержит циклические структуры в некоторых реализациях
  • зависит от runtime состояния формы

Итоговая модель представления

Обобщённая модель:

  • errors — дерево
  • узлы соответствуют path
  • листья содержат описание ошибки
  • массивы индексируются числами
  • Yup выступает источником структуры ошибок
  • резолвер выполняет трансформацию ValidationError → объект формы