From b59f247d895751a125f828b4f215d4d7be59e2c8 Mon Sep 17 00:00:00 2001 From: hemraj-007 <140829250+hemraj-007@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:50:22 +0530 Subject: [PATCH] fix: bump array version on reset so array fields re-render Bump _arrayVersion after form.reset and form.resetField so React array fields re-render when reset shortens the array. Fixes #2228 Co-authored-by: Cursor --- .changeset/fix-array-reset-rerender.md | 8 ++++ packages/form-core/src/FormApi.ts | 13 +++++++ packages/form-core/tests/FormApi.spec.ts | 17 +++++++++ packages/react-form/tests/useField.test.tsx | 42 +++++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 .changeset/fix-array-reset-rerender.md diff --git a/.changeset/fix-array-reset-rerender.md b/.changeset/fix-array-reset-rerender.md new file mode 100644 index 000000000..a9660b655 --- /dev/null +++ b/.changeset/fix-array-reset-rerender.md @@ -0,0 +1,8 @@ +--- +'@tanstack/form-core': patch +'@tanstack/react-form': patch +--- + +Bump `_arrayVersion` when resetting array fields so adapters re-render after `form.reset()` or `form.resetField()` changes array length. + +Fixes #2228 diff --git a/packages/form-core/src/FormApi.ts b/packages/form-core/src/FormApi.ts index d710cd105..0c8c7a8a5 100644 --- a/packages/form-core/src/FormApi.ts +++ b/packages/form-core/src/FormApi.ts @@ -1847,6 +1847,15 @@ export class FormApi< fieldMetaBase, }) }) + + const helper = metaHelper(this) + for (const fieldKey of Object.keys( + this.fieldInfo, + ) as DeepKeys[]) { + if (Array.isArray(this.getFieldValue(fieldKey))) { + helper.bumpArrayVersion(fieldKey) + } + } } /** @@ -2954,6 +2963,10 @@ export class FormApi< : prev.values, } }) + + if (Array.isArray(this.getFieldValue(field))) { + metaHelper(this).bumpArrayVersion(field) + } } /** diff --git a/packages/form-core/tests/FormApi.spec.ts b/packages/form-core/tests/FormApi.spec.ts index 024b319f0..53d65ff7e 100644 --- a/packages/form-core/tests/FormApi.spec.ts +++ b/packages/form-core/tests/FormApi.spec.ts @@ -125,6 +125,23 @@ describe('form api', () => { }) }) + it('should bump array version when resetting to a shorter array', () => { + const form = new FormApi({ + defaultValues: { + items: [1, 2, 3], + }, + }) + form.mount() + + const field = new FieldApi({ form, name: 'items' }) + field.mount() + + form.reset({ items: [4] }) + + expect(form.getFieldValue('items')).toEqual([4]) + expect(form.getFieldMeta('items')?._arrayVersion).toBe(1) + }) + it('form should reset default value when resetting in onSubmit', async () => { const defaultValues = { name: '', diff --git a/packages/react-form/tests/useField.test.tsx b/packages/react-form/tests/useField.test.tsx index 445416594..aff1e06ad 100644 --- a/packages/react-form/tests/useField.test.tsx +++ b/packages/react-form/tests/useField.test.tsx @@ -1644,6 +1644,48 @@ describe('useField', () => { expect(getByTestId('item-0')).toHaveTextContent('Alice') }) + it('should rerender array field when reset to a shorter array', async () => { + // Regression test for https://github.com/TanStack/form/issues/2228 + function Comp() { + const form = useForm({ + defaultValues: { + items: [1, 2, 3], + }, + }) + + return ( + <> + + + {(field) => ( +
    + {field.state.value.map((item, i) => ( +
  1. + {item} +
  2. + ))} +
+ )} +
+ + ) + } + + const { getByTestId } = render() + expect(getByTestId('list').children).toHaveLength(3) + + await user.click(getByTestId('reset')) + + expect(getByTestId('list').children).toHaveLength(1) + expect(getByTestId('item-0')).toHaveTextContent('4') + }) + it('should handle defaultValue without setstate-in-render error', async () => { // Spy on console.error before rendering const consoleErrorSpy = vi.spyOn(console, 'error')