Skip to content

fix(form-core): keep reset(values) baseline on update() with unchanged props defaultValues#2235

Open
xianjianlf2 wants to merge 1 commit into
TanStack:mainfrom
xianjianlf2:fix/1681-reset-in-onsubmit
Open

fix(form-core): keep reset(values) baseline on update() with unchanged props defaultValues#2235
xianjianlf2 wants to merge 1 commit into
TanStack:mainfrom
xianjianlf2:fix/1681-reset-in-onsubmit

Conversation

@xianjianlf2

@xianjianlf2 xianjianlf2 commented Jul 9, 2026

Copy link
Copy Markdown

Fixes #1681

Problem

Calling form.reset(newValues) inside onSubmit while a component subscribes to isDirty reverts the form to the original default values instead of the new ones.

The isDirty change re-renders the component, which re-runs the formApi.update(opts) layout effect with the unchanged props defaultValues. update() compared the incoming defaultValues against this.options.defaultValues — but reset(values) had just mutated that field, so the unchanged props looked like a real change and (because reset also cleared isTouched) clobbered the freshly-reset values back to the original defaults.

Fix

Track the defaultValues seen on the previous update() call and compare against that instead. When the props defaultValues did not actually change, preserve the current baseline (e.g. one set by reset(values)) so the values — and isDirty / isDefaultValue — stay correct after a reset. Fixed in form-core, so the fix covers all framework adapters.

Tests

  • form-core: regression test for the update() / reset() race.
  • react-form: integration test reproducing the exact issue (component-level isDirty subscription + reset in onSubmit).

Both tests fail on main and pass with this change. Full form-core (499) and react-form (124) suites pass with no type errors.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where form values could revert after resetting during submit and then updating the form.
    • Preserved reset values so the form stays in the expected state after submission.
    • Improved dirty-state handling so forms return to pristine correctly after a reset.

…d props defaultValues

Calling form.reset(newValues) inside onSubmit while a component subscribes to
isDirty reverted the form to the original default values instead of the new ones.
The isDirty change re-renders the component, re-running the formApi.update(opts)
layout effect with the unchanged props defaultValues. update() compared against
this.options.defaultValues, which reset() had just mutated, so the unchanged props
looked like a real change and (because reset also cleared isTouched) clobbered the
freshly reset values.

Track the defaultValues seen on the previous update() call and compare against that
instead; when the props defaultValues did not actually change, preserve the current
baseline (e.g. one set by reset(values)) so values and isDirty/isDefaultValue stay
correct after a reset. Fixed in form-core so it covers all framework adapters.

Fixes TanStack#1681

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

FormApi now tracks the defaultValues baseline from the previous update() call in a new private field, using it to detect genuine prop changes versus reset()-driven mutations. This prevents update() from overriding values set by reset() calls made inside onSubmit. Tests added in form-core and react-form.

Changes

Reset/update defaultValues fix

Layer / File(s) Summary
Baseline tracking and update() logic
packages/form-core/src/FormApi.ts
Adds _prevUpdateDefaultValues field and reworks update() to compute defaultValuesChanged against the stored baseline instead of this.options.defaultValues, preserving reset()-set values and updating shouldUpdateValues accordingly.
Regression tests for reset-during-submit
packages/form-core/tests/FormApi.spec.ts, packages/react-form/tests/useForm.test.tsx
Adds tests verifying that calling reset() inside onSubmit with new values is preserved after a subsequent update() call with unchanged defaultValues, including a scenario with an isDirty store subscription.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • TanStack/form#2190: Also modifies FormApi.update()'s shouldUpdateValues/defaultValues logic affecting array field version bumping.

Suggested reviewers: crutchcorn

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title is concise and accurately summarizes the core fix in form-core.
Description check ✅ Passed Description covers the bug, fix, and tests, though it omits the template's checklist and release-impact sections.
Linked Issues check ✅ Passed The code and tests address #1681 by preserving reset(values) after onSubmit when isDirty subscriptions trigger update().
Out of Scope Changes check ✅ Passed The changes stay focused on the reported reset/update race and the supporting regression tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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.

🧹 Nitpick comments (1)
packages/form-core/tests/FormApi.spec.ts (1)

1235-1269: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider asserting isDirty after update() to verify the PR objective at the unit level.

The test verifies the reset value survives the subsequent update(), but doesn't explicitly assert isDirty after the update() call. The PR objectives state that isDirty should be correct after reset. Adding this assertion at the FormApi level would catch regressions even if the React adapter test is skipped.

💚 Suggested addition
     // the reset values must survive: props defaultValues never actually changed
     expect(form.getFieldValue('name')).toEqual('new-default')
+    expect(form.state.isDirty).toBe(false)
   })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/form-core/tests/FormApi.spec.ts` around lines 1235 - 1269, The
FormApi regression test covers that `reset()` values survive a later `update()`,
but it does not verify the dirty state after the update. In `FormApi.spec.ts`,
extend the `it('should keep reset() values when a subsequent update() reuses the
original props defaultValues')` case to assert `form.state.isDirty` after
`form.update(...)`, so the unit test directly checks the PR’s intended `isDirty`
behavior in `FormApi.reset()`/`FormApi.update()`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/form-core/tests/FormApi.spec.ts`:
- Around line 1235-1269: The FormApi regression test covers that `reset()`
values survive a later `update()`, but it does not verify the dirty state after
the update. In `FormApi.spec.ts`, extend the `it('should keep reset() values
when a subsequent update() reuses the original props defaultValues')` case to
assert `form.state.isDirty` after `form.update(...)`, so the unit test directly
checks the PR’s intended `isDirty` behavior in
`FormApi.reset()`/`FormApi.update()`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1f38254d-e2a8-4cc0-b614-2cfa9926663a

📥 Commits

Reviewing files that changed from the base of the PR and between 6a73479 and 8fd158f.

📒 Files selected for processing (3)
  • packages/form-core/src/FormApi.ts
  • packages/form-core/tests/FormApi.spec.ts
  • packages/react-form/tests/useForm.test.tsx

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.

form.reset during onSubmit ignores new default values

1 participant