Skip to content

fix: prevent field array ghost elements with keepDirtyValues#13188

Merged
bluebill1049 merged 3 commits intoreact-hook-form:masterfrom
a28689604:fix/field-array-ghost-elements-keep-dirty-values
Jan 1, 2026
Merged

fix: prevent field array ghost elements with keepDirtyValues#13188
bluebill1049 merged 3 commits intoreact-hook-form:masterfrom
a28689604:fix/field-array-ghost-elements-keep-dirty-values

Conversation

@a28689604
Copy link
Contributor

@a28689604 a28689604 commented Dec 9, 2025

Proposed Changes

As mentioned in issue #12489, when using useFieldArray with the values prop and resetOptions: { keepDirtyValues: true }, removed field array items were being re-inserted as "ghost" elements on subsequent appends.

Root cause

During reset with keepDirtyValues: true, the logic iterates through _names.mount (which contains field names like test.0.value, test.1.value) to determine which values to preserve. However:

  1. When array items are removed, their field names remain in _names.mount
  2. The dirtyFields state is also preserved from before the reset
  3. During the keepDirtyValues loop, the code attempted to update fields that no longer existed in _formValues
  4. For clean fields, calling setValue() with a path to a non-existent array index created ghost elements (e.g., test.1.value created [{ value: undefined }])

Fixes

  • Only preserve dirty values if the field still exists in current form values (existingValue !== undefined)
  • Only update clean fields if they exist in the new reset values (newValue !== undefined)
  • Skip processing entirely for fields that have been removed from the form
    This prevents the code from creating array elements for field paths that no longer exist.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Fixes #12489

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where removed field array items were being re-inserted as "ghost" elements during form reset with keepDirtyValues enabled. The issue occurred because stale field names remained in _names.mount after removal, and the reset logic attempted to set values for non-existent array indices, inadvertently creating new array elements.

Key changes:

  • Modified the keepDirtyValues logic to check if field values exist before setting them
  • Added comprehensive test coverage for the field array ghost elements scenario

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/logic/createFormControl.ts Added undefined checks to prevent setting values for non-existent field paths, fixing the ghost elements bug
src/tests/useFieldArray/remove.test.tsx Added comprehensive test that reproduces and validates the fix for the ghost elements issue

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1368 to 1370
if (isDirty && existingValue !== undefined) {
set(values, fieldName, existingValue);
} else if (!isDirty && newValue !== undefined) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use the isUndefined util function

@a28689604 a28689604 force-pushed the fix/field-array-ghost-elements-keep-dirty-values branch from b08e960 to 71266aa Compare December 16, 2025 07:46
Add existence checks in keepDirtyValues logic to skip fields that have
been removed from the form values, preventing ghost array elements.

Signed-off-by: a28689604 <a28689604@gmail.com>
Refactor the logic in createFormControl to use isUndefined checks
instead of direct comparisons to undefined.

Signed-off-by: a28689604 <a28689604@gmail.com>
@a28689604 a28689604 force-pushed the fix/field-array-ghost-elements-keep-dirty-values branch from e07bd74 to 20dc074 Compare January 1, 2026 13:27
@bluebill1049 bluebill1049 merged commit c54ebf9 into react-hook-form:master Jan 1, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

issue: useFieldArray re-insert removed items automatically with keepDirtyValue

2 participants