В динамической форме пользователь добавляет, удаляет и переставляет строки, а сервер получает цену от одного элемента вместе с названием другого. Обычно массив используют одновременно как порядок интерфейса и идентичность данных, а index становится key и частью имени поля.

Исправление начинается со стабильного ID каждой строки. Порядок можно менять, но identity должна сохраняться. Сервер принимает массив объектов, проверяет каждый объект независимо и не доверяет индексам как бизнес-идентификаторам.

Что проверить в первую очередь

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

  • Запишите исходный массив, последовательность удаления/перестановки и итоговый payload.
  • Проверьте key компонента: использование индекса опасно при изменении порядка.
  • Сравните register/name полей с фактической структурой отправляемого JSON или FormData.
  • Проверьте, как сервер связывает ошибки с конкретной строкой.

Почему возникает проблема

У подобных сбоев редко бывает одна универсальная причина. На итог одновременно влияют конфигурация приложения, окружение, данные, кеш, права и внешние сервисы. Проверка должна идти от внешнего симптома к конкретному уровню, на котором впервые появляется неверное состояние.

  • React/Vue переиспользует компонент с key=index и сохраняет внутреннее состояние другой строки.
  • После splice индексы сдвигаются, а зарегистрированные имена полей остаются прежними.
  • DOM-значение и состояние формы управляются разными источниками.
  • Backend обновляет сущности по позиции массива вместо постоянного ID.
  • Асинхронная валидация возвращает ошибку по старому индексу после перестановки.

Пошаговая диагностика

Диагностику проводите на копии или в контролируемое время. Перед изменениями сохраните конфигурацию, данные и журналы. Каждый шаг должен отвечать на один вопрос и оставлять измеримый результат: код ответа, запись в логе, состояние процесса, значение поля или воспроизводимый тест.

  • Добавьте каждой строке временный UUID и выводите его рядом с payload только в тестовой среде.
  • Повторите добавление A/B/C, удаление B и редактирование C, затем сравните state, DOM и запрос.
  • Проверьте, размонтируется ли удаленная строка и снимается ли ее регистрация в библиотеке форм.
  • Сравните controlled и uncontrolled поля, defaultValue и value.
  • На сервере залогируйте только ID и позиции объектов без чувствительных значений.

Идентичность строки и ее позиция — разные вещи

Позиция отвечает за отображение, а ID — за принадлежность значения конкретной сущности. Смешение этих понятий создает ошибки после любого изменения списка.

  • Новой строке назначайте client_id один раз при создании и не меняйте при сортировке.
  • Существующая запись должна передавать серверный id, а новая — отдельный безопасный client_id.
  • Используйте стабильный ID как key компонента, но не показывайте служебный ID пользователю.
  • Ошибки возвращайте в карте по ID строки и имени поля, а не только по номеру.
  • Порядок передавайте отдельным полем position, если он имеет бизнес-значение.

Как исправить проблему

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

  • Замените key=index на стабильный id/client_id.
  • Храните массив объектов в одном источнике состояния и обновляйте по ID.
  • При удалении явно unregister поля, если библиотека сохраняет их значения.
  • Сформируйте payload перед отправкой из текущего состояния, исключая удаленные элементы.
  • На backend валидируйте допустимость ID, принадлежность записи пользователю и уникальность position.

Безопасный порядок внедрения

  • Сохраните резервную копию затрагиваемых файлов, базы и конфигурации, а также заранее опишите способ отката.
  • Воспроизведите сбой на тестовой записи, учетной записи или отдельном окружении без реальных платежей и рассылок.
  • Вносите по одному логическому изменению, фиксируя его в системе контроля версий или журнале работ.
  • Не отключайте права, проверку входных данных и защитные механизмы только ради исчезновения сообщения об ошибке.
  • После выкладки контролируйте логи, метрики и ключевой пользовательский сценарий, а не только открытие одной страницы.

Как проверить результат

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

  • Добавление, удаление первой/средней строки и перестановка не смешивают значения.
  • Ошибки остаются рядом с правильной строкой после изменения порядка.
  • Повторное редактирование существующих и новых строк обновляет нужные записи без дублей.
  • Пустые, удаленные и скрытые поля не попадают в запрос неожиданно.

Типичные ошибки при исправлении

  • Менять только визуальный key, оставляя бизнес-обновление по индексу.
  • Генерировать новый UUID при каждом рендере и тем самым постоянно размонтировать поля.
  • Доверять присланному ID без проверки владельца записи.
  • Сохранять удаленные значения в скрытом состоянии и случайно отправлять их.

Как предотвратить повторение

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

  • Пишите тесты на add/remove/reorder и ошибки сервера для середины списка.
  • Разделяйте ID, position и отображаемый номер в модели данных.
  • Используйте типизированную схему payload на клиенте и сервере.
  • Не применяйте индекс как key для редактируемых списков.

Что подготовить для разбора

  • Краткое описание ожидаемого и фактического поведения без паролей, токенов и персональных данных.
  • Точное время и последовательность действий, после которых появляется проблема.
  • Версии приложения, окружения и зависимостей, а также перечень последних изменений.
  • Фрагменты журналов с контекстом до и после ошибки; секреты в них необходимо скрыть.
  • Описание уже выполненных проверок и способ безопасно повторить проблему.

Частые вопросы

Всегда ли нельзя использовать index как key?

Для статичного списка без изменения порядка это допустимо, но для редактируемых, удаляемых и сортируемых строк нужен стабильный идентификатор.

Что делать с новыми строками без ID базы?

Назначать временный client_id на клиенте и передавать его для связи ошибок. После сохранения сервер вернет постоянный ID.

Когда нужна помощь специалиста

Если динамическая форма путает строки, ошибки или сохраняемые записи, я могу воспроизвести сценарий, привести модель к стабильным ID и проверить frontend и backend на удаление, сортировку и повторную отправку.