diff --git a/docs/demo/list-unmount.md b/docs/demo/list-unmount.md
new file mode 100644
index 00000000..b7154eec
--- /dev/null
+++ b/docs/demo/list-unmount.md
@@ -0,0 +1,3 @@
+## list
+
+
diff --git a/docs/examples/list-unmount.tsx b/docs/examples/list-unmount.tsx
new file mode 100644
index 00000000..b62f9586
--- /dev/null
+++ b/docs/examples/list-unmount.tsx
@@ -0,0 +1,56 @@
+import React, { useState } from 'react';
+import Form from 'rc-field-form';
+import Input from './components/Input';
+import LabelField from './components/LabelField';
+
+const Demo = () => {
+ const [form] = Form.useForm();
+ const [isShow, setIsShow] = useState(true);
+
+ return (
+
+
{() => JSON.stringify(form.getFieldsValue(), null, 2)}
+
+
+ {fields => {
+ return (
+
+ );
+ }}
+
+
+
+
+
+ );
+};
+
+export default Demo;
diff --git a/src/useForm.ts b/src/useForm.ts
index d948c074..7135aead 100644
--- a/src/useForm.ts
+++ b/src/useForm.ts
@@ -910,6 +910,8 @@ export class FormStore {
const namePathList: InternalNamePath[] | undefined = provideNameList
? nameList.map(getNamePath)
: [];
+ // Same namePathList, but does not include Form.List name
+ const finalValueNamePathList = [...namePathList];
// Collect result in promise list
const promiseList: Promise[] = [];
@@ -921,9 +923,17 @@ export class FormStore {
const { recursive, dirty } = options || {};
this.getFieldEntities(true).forEach((field: FieldEntity) => {
+ const fieldNamePath = field.getNamePath();
+
// Add field if not provide `nameList`
if (!provideNameList) {
- namePathList.push(field.getNamePath());
+ if (
+ // When Form.List has a value, filter Form.List `name`
+ !(field.isList() && namePathList.some(name => matchNamePath(name, fieldNamePath, true)))
+ ) {
+ finalValueNamePathList.push(fieldNamePath);
+ }
+ namePathList.push(fieldNamePath);
}
// Skip if without rule
@@ -936,7 +946,6 @@ export class FormStore {
return;
}
- const fieldNamePath = field.getNamePath();
validateNamePathList.add(fieldNamePath.join(TMP_SPLIT));
// Add field validate rule in to promise list
@@ -1000,7 +1009,7 @@ export class FormStore {
const returnPromise: Promise = summaryPromise
.then((): Promise => {
if (this.lastValidatePromise === summaryPromise) {
- return Promise.resolve(this.getFieldsValue(namePathList));
+ return Promise.resolve(this.getFieldsValue(finalValueNamePathList));
}
return Promise.reject([]);
})
diff --git a/tests/list.test.tsx b/tests/list.test.tsx
index 598eb5f5..e21a8f84 100644
--- a/tests/list.test.tsx
+++ b/tests/list.test.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
import { fireEvent, render, act } from '@testing-library/react';
import { resetWarned } from '@rc-component/util/lib/warning';
import Form, { Field, List } from '../src';
@@ -937,4 +937,98 @@ describe('Form.List', () => {
expect(formRef.current!.getFieldValue('list')).toEqual([{ user: '1' }, { user: '3' }]);
});
+
+ it('list unmount', async () => {
+ const valueRef = React.createRef();
+
+ const Demo = () => {
+ const [isShow, setIsShow] = useState(true);
+ return (
+
+ {fields => {
+ return fields.map(field => (
+
+
+
+
+ {isShow && (
+
+
+
+ )}
+
+ ));
+ }}
+
+
+
+
+ );
+ };
+
+ const { queryByTestId } = render();
+ fireEvent.click(queryByTestId('submit'));
+ await act(async () => {
+ await timeout();
+ });
+ expect(valueRef.current).toEqual({
+ users: [
+ { name: 'a', age: '1' },
+ { name: 'b', age: '2' },
+ ],
+ });
+
+ fireEvent.click(queryByTestId('hide'));
+ fireEvent.click(queryByTestId('submit'));
+ await act(async () => {
+ await timeout();
+ });
+ expect(valueRef.current).toEqual({ users: [{ name: 'a' }, { name: 'b' }] });
+ });
+
+ it('list rules', async () => {
+ const onFinishFailed = jest.fn();
+
+ const Demo = () => {
+ return (
+ Promise.reject('error') }]}>
+ {fields => {
+ return fields.map(field => (
+
+
+
+ ));
+ }}
+
+
+
+ );
+ };
+
+ const { queryByTestId } = render();
+ fireEvent.click(queryByTestId('submit'));
+ await act(async () => {
+ await timeout();
+ });
+
+ expect(onFinishFailed).toHaveBeenCalled();
+ });
});