В динамической форме пользователь добавляет, удаляет и переставляет строки, а сервер получает цену от одного элемента вместе с названием другого. Обычно массив используют одновременно как порядок интерфейса и идентичность данных, а 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 на удаление, сортировку и повторную отправку.