diff --git a/src/useForm.ts b/src/useForm.ts index e2cd4b70b..ce08d5bd8 100644 --- a/src/useForm.ts +++ b/src/useForm.ts @@ -346,8 +346,16 @@ export class FormStore { // We need fill the list as [] if Form.List is empty listNamePaths.forEach(namePath => { - if (!getValue(mergedValues, namePath)) { - mergedValues = setValue(mergedValues, namePath, []); + // Form.List 的数组结构(add/remove)会先同步更新 store, + // 而对应的子 Field 要到下一次 commit 才会 register。 + // 在这段 render 时序中,fieldEntities 仍然是“上一帧”的结果, + // 用它来拼 list 会得到不完整的数据。 + // 因此 List 根节点的值始终以 store 为准,避免依赖 Field 注册时序。 + const storeListValue = getValue(this.store, namePath); + + if (storeListValue !== undefined) { + mergedValues = setValue(mergedValues, namePath, storeListValue); + return; } }); diff --git a/tests/list.test.tsx b/tests/list.test.tsx index 8a207e240..7491126c0 100644 --- a/tests/list.test.tsx +++ b/tests/list.test.tsx @@ -1139,4 +1139,39 @@ describe('Form.List', () => { { list: [{ name: 'John', tags: ['react', 'ts', 'redux'] }] }, ); }); + + it('getFieldsValue should return list root value when Form.List is not wrapped by parent Field', async () => { + let operation: ListOperations; + + const [container] = generateForm((fields, opt) => { + operation = opt; + return ( +
+ {fields.map(field => ( +
+ + + + + + +
+ ))} +
+ ); + }); + + // First add a row + act(() => { + operation.add(); + }); + + // Fill some values + await changeValue(getInput(container, 0), 'n1'); // list[0].name + await changeValue(getInput(container, 1), '1'); // list[0].value + + expect(form.current?.getFieldsValue(['list'])).toEqual({ + list: [{ name: 'n1', value: '1' }], + }); + }); });