From 9718bdcbe6b04c26eebdb05e4127ba7a4f2c2157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 23 Mar 2026 11:22:36 +0800 Subject: [PATCH 1/3] test: add mixed field list onValuesChange case --- tests/dependencies.test.tsx | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/dependencies.test.tsx b/tests/dependencies.test.tsx index 8ba8260d..01159f16 100644 --- a/tests/dependencies.test.tsx +++ b/tests/dependencies.test.tsx @@ -302,4 +302,49 @@ describe('Form.Dependencies', () => { await changeValue(getInput(container), '1'); matchError(container, false); }); + + it('mixed field list should not missing value with onValuesChange', () => { + const onValuesChange = jest.fn(); + + const { container } = render( +
+ + {fields => + fields.map(field => ( +
+ + + + + + {(triggerFields, { add }) => ( + <> + {triggerFields.map(triggerField => ( + + + + ))} + + + )} + +
+ )) + } +
+
, + ); + + fireEvent.click(container.querySelector('button')!); + + expect(onValuesChange).toHaveBeenLastCalledWith( + expect.anything(), + { rules: [{ name: 'test', triggers: ['trigger_1'] }] }, + ); + }); }); From 9cb168552f8c9218f067d9720ecaa59846261397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 23 Mar 2026 11:37:46 +0800 Subject: [PATCH 2/3] fix: preserve sibling values for nested list changes --- src/hooks/useForm.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts index ebbefd92..c660f9a2 100644 --- a/src/hooks/useForm.ts +++ b/src/hooks/useForm.ts @@ -1,5 +1,4 @@ import { merge } from '@rc-component/util/lib/utils/set'; -import { mergeWith } from '@rc-component/util'; import warning from '@rc-component/util/lib/warning'; import * as React from 'react'; import { HOOK_MARK } from '../FieldContext'; @@ -779,14 +778,9 @@ export class FormStore { const { onValuesChange } = this.callbacks; if (onValuesChange) { - const fieldEntity = this.getFieldsMap(true).get(namePath); const changedValues = cloneByNamePathList(this.store, [namePath]); const allValues = this.getFieldsValue(); - // Merge changedValues into allValues to ensure allValues contains the latest changes - const mergedAllValues = mergeWith([allValues, changedValues], { - // When value is array, it means trigger by Form.List which should replace directly - prepareArray: current => (fieldEntity?.isList() ? [] : [...(current || [])]), - }); + const mergedAllValues = setValue(allValues, namePath, getValue(changedValues, namePath)); onValuesChange(changedValues, mergedAllValues); } From 5f0189519ba5ff0fe0f38dc6d617bf5e745bd592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 23 Mar 2026 11:59:20 +0800 Subject: [PATCH 3/3] test: cover nested list remove onValuesChange --- tests/dependencies.test.tsx | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/dependencies.test.tsx b/tests/dependencies.test.tsx index 01159f16..d81533b0 100644 --- a/tests/dependencies.test.tsx +++ b/tests/dependencies.test.tsx @@ -347,4 +347,49 @@ describe('Form.Dependencies', () => { { rules: [{ name: 'test', triggers: ['trigger_1'] }] }, ); }); + + it('mixed field list remove should not missing value with onValuesChange', () => { + const onValuesChange = jest.fn(); + + const { container } = render( +
+ + {fields => + fields.map(field => ( +
+ + + + + + {(triggerFields, { remove }) => ( + <> + {triggerFields.map(triggerField => ( + + + + ))} + + + )} + +
+ )) + } +
+
, + ); + + fireEvent.click(container.querySelector('button')!); + + expect(onValuesChange).toHaveBeenLastCalledWith( + expect.anything(), + { rules: [{ name: 'test', triggers: ['trigger_2'] }] }, + ); + }); });