Skip to content

Fix #366: keepDirtyOnReinitialize with array fields#538

Merged
erikras merged 4 commits into
mainfrom
fix-366-keepdirty-arrays
Feb 17, 2026
Merged

Fix #366: keepDirtyOnReinitialize with array fields#538
erikras merged 4 commits into
mainfrom
fix-366-keepdirty-arrays

Conversation

@erikras-richard-agent

@erikras-richard-agent erikras-richard-agent commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

Problem: When keepDirtyOnReinitialize is true and array fields are used (e.g., with final-form-arrays), pristine child fields don't update to new initial values. The parent array field's dirty value overwrites them.

Root Cause: When saving dirty values, the code saves ALL dirty fields including parent array fields (e.g., customers) AND their children (e.g., customers[0].firstName). When setting values back, the parent array value overwrites pristine children.

Example Bug:

// Register both array field and children
form.registerField('customers', ...) // Array field
form.registerField('customers[0].firstName', ...) // Child
form.registerField('customers[1].lastName', ...) // Child

// Modify one child
form.change('customers[0].firstName', 'Modified')

// Reinitialize with new data
form.initialize({ customers: [
  { firstName: 'New1', lastName: 'NewLast1' },
  { firstName: 'New2', lastName: 'NewLast2' }
]})

// BUG: customers[1].lastName keeps old value instead of updating to 'NewLast2'
// because 'customers' array was saved as dirty and overwrote it

Solution: When saving dirty values, skip parent fields if child fields are registered. For example, if both customers and customers[0].firstName are registered, only save dirty values for the child fields.

This allows:

  • ✅ Dirty children keep their modified values
  • ✅ Pristine children update to new initial values
  • ✅ Parent array doesn't override children

Testing:

  • Added test with array field + child fields
  • Verifies modified child keeps value, pristine child updates
  • All existing tests pass

Fixes #366

Summary by CodeRabbit

  • Bug Fixes

    • Refined dirty-state persistence during form reinitialization so edits inside nested array fields are preserved while untouched values adopt new initial data.
  • Tests

    • Added test coverage validating dirty-state behavior for nested array fields during reinitialization.
  • Chores

    • Updated build metadata size limit for the distributed bundle.

When keepDirtyOnReinitialize is true and array fields are used (e.g.,
final-form-arrays), pristine child fields weren't updating to new
initial values because the parent array field's dirty value was
overwriting them.

Fix: When saving dirty values, skip parent fields if child fields are
registered. For example, if both 'customers' and 'customers[0].firstName'
are registered, only save dirty values for the more specific child fields.

This allows pristine children to update while dirty children keep their
modified values, which is the expected keepDirtyOnReinitialize behavior.

Added test verifying:
- Modified child field keeps dirty value
- Pristine child field updates to new initial value
- Parent array field doesn't override children
@coderabbitai

coderabbitai Bot commented Feb 16, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Updates FinalForm reinitialization to avoid persisting parent keys that have registered child fields when keepDirtyOnReinitialize is true, and adds a test verifying nested array-field dirty behavior across reinitialize.

Changes

Cohort / File(s) Summary
Test: keepDirtyOnReinitialize with arrays
src/FinalForm.arrays-keepdirty.test.ts
Adds a new test that registers an array field and nested child fields, mutates a nested child, reinitializes, and asserts the dirty nested child retains its value while a pristine nested child updates to new initial values.
Core: dirty-value collection
src/FinalForm.ts
Modifies initialization logic so savedDirtyValues excludes a field key when there are registered child keys beneath it, preventing parent array keys from overriding nested child dirty values during reinitialize.
Meta: package manifest
package.json
Bumped size-limit entry for dist/final-form.cjs.js from 6.55kB to 6.62kB.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • erikras

Poem

🐇
I hopped through arrays at break of day,
Kept one small change while others slipped away.
Parents stepped back, let children decide,
Pristine ones welcomed a fresh new tide.
A rabbit cheers — reinitialize with pride.

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix #366: keepDirtyOnReinitialize with array fields' clearly and specifically describes the main change: fixing the keepDirtyOnReinitialize behavior for array fields as identified in issue #366.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from #366: it prevents parent array fields from overriding child fields during reinitialize by excluding parent fields when child subfields are registered, allowing pristine children to update while dirty children retain values.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the keepDirtyOnReinitialize issue: the core logic fix in FinalForm.ts, a targeted test verifying the fix, and a size-limit adjustment reflecting the code changes.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-366-keepdirty-arrays

Comment @coderabbitai help to get the list of available commands and usage tips.

The child field detection logic adds ~54 bytes to prevent parent
array fields from overwriting pristine children when keepDirtyOnReinitialize
is enabled. Small size increase is acceptable for fixing the bug.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@src/FinalForm.arrays-keepdirty.test.ts`:
- Around line 47-48: Remove the stale inline comment preceding the failing
assertion: delete the comment text "// BUG: This fails - it keeps the old value
'Smith' instead of updating to 'NewSmith'" that sits above the
expect(lastName1State.value).toBe('NewSmith') assertion so the test no longer
contains misleading commentary; leave the
expect(lastName1State.value).toBe('NewSmith') line and surrounding test logic
unchanged.

Comment thread src/FinalForm.arrays-keepdirty.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@src/FinalForm.arrays-keepdirty.test.ts`:
- Around line 43-47: Replace the mixed assertion that reads the form state via
getIn(form.getState().values, 'customers[0].firstName') with the field
subscriber variable firstName0State.value to keep assertions consistent and
verify the subscriber was notified after reinitialization; update the
expectation that currently checks the modified first name to use
firstName0State.value and leave the lastName1State.value assertion intact so
both field-state subscriptions are validated.

Comment thread src/FinalForm.arrays-keepdirty.test.ts
@erikras
erikras merged commit c264d12 into main Feb 17, 2026
5 checks passed
@erikras-richard-agent

Copy link
Copy Markdown
Contributor Author

Published in v5.0.1

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.

keepDirtyOnReinitialize does not work with final-form-arrays

2 participants