diff --git a/examples/list.tsx b/examples/list.tsx
index 6dc84227..76a08a78 100644
--- a/examples/list.tsx
+++ b/examples/list.tsx
@@ -21,7 +21,10 @@ const Demo = () => {
console.log('values:', values);
}}
style={{ border: '1px solid red', padding: 15 }}
+ preserve={false}
>
+
{() => JSON.stringify(form.getFieldsValue(), null, 2)}
+
{(fields, { add, remove }) => {
console.log('Demo Fields:', fields);
diff --git a/src/Field.tsx b/src/Field.tsx
index 0c8f534b..44ca5f69 100644
--- a/src/Field.tsx
+++ b/src/Field.tsx
@@ -73,13 +73,13 @@ export interface InternalFieldProps {
initialValue?: any;
onReset?: () => void;
preserve?: boolean;
+
+ /** @private Passed by Form.List props. Do not use since it will break by path check. */
+ isListField?: boolean;
}
export interface FieldProps extends Omit {
name?: NamePath;
-
- /** @private Passed by Form.List props. */
- isListField?: boolean;
}
export interface FieldState {
@@ -102,7 +102,7 @@ class Field extends React.Component void | null = null;
+ private cancelRegisterFunc: (isListField?: boolean, preserve?: boolean) => void | null = null;
private destroy = false;
@@ -140,10 +140,10 @@ class Field extends React.Component {
- const { preserve } = this.props;
+ const { preserve, isListField } = this.props;
if (this.cancelRegisterFunc) {
- this.cancelRegisterFunc(preserve);
+ this.cancelRegisterFunc(isListField, preserve);
}
this.cancelRegisterFunc = null;
};
@@ -498,13 +498,21 @@ class Field extends React.Component = ({ name, isListField, ...restProps }) => {
+const WrapperField: React.FC = ({ name, ...restProps }) => {
const namePath = name !== undefined ? getNamePath(name) : undefined;
let key: string = 'keep';
- if (!isListField) {
+ if (!restProps.isListField) {
key = `_${(namePath || []).join('_')}`;
}
+
+ if (process.env.NODE_ENV !== 'production') {
+ warning(
+ restProps.preserve !== false || !restProps.isListField,
+ '`preserve` should not apply on Form.List fields.',
+ );
+ }
+
return ;
};
diff --git a/src/useForm.ts b/src/useForm.ts
index 94e6a73f..a0aa8eef 100644
--- a/src/useForm.ts
+++ b/src/useForm.ts
@@ -493,12 +493,12 @@ export class FormStore {
}
// un-register field callback
- return (preserve?: boolean) => {
+ return (isListField?: boolean, preserve?: boolean) => {
this.fieldEntities = this.fieldEntities.filter(item => item !== entity);
// Clean up store value if preserve
const mergedPreserve = preserve !== undefined ? preserve : this.preserve;
- if (mergedPreserve === false) {
+ if (mergedPreserve === false && !isListField) {
const namePath = entity.getNamePath();
if (this.getFieldValue(namePath) !== undefined) {
this.store = setValue(this.store, namePath, undefined);
diff --git a/tests/preserve.test.tsx b/tests/preserve.test.tsx
index 7b8e4a6d..f3a18293 100644
--- a/tests/preserve.test.tsx
+++ b/tests/preserve.test.tsx
@@ -1,7 +1,7 @@
-/* eslint-disable no-template-curly-in-string */
+/* eslint-disable no-template-curly-in-string, arrow-body-style */
import React from 'react';
import { mount } from 'enzyme';
-import Form from '../src';
+import Form, { FormInstance } from '../src';
import InfoField from './common/InfoField';
import timeout from './common/timeout';
@@ -74,5 +74,68 @@ describe('Form.Preserve', () => {
await matchTest(true, { keep: 233 });
await matchTest(false, { keep: 233, remove: 666 });
});
+
+ it('form perishable should not crash Form.List', async () => {
+ let form: FormInstance;
+
+ const wrapper = mount(
+
+ {(fields, { remove }) => {
+ return (
+
+ {fields.map(field => (
+
+
+
+ ))}
+
+ );
+ }}
+
+ ,
+ );
+
+ wrapper.find('button').simulate('click');
+ wrapper.update();
+
+ expect(form.getFieldsValue()).toEqual({ list: ['bamboo', 'little'] });
+ });
+
+ it('warning when Form.List use preserve', () => {
+ const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
+
+ mount(
+
+ {fields =>
+ fields.map(field => (
+
+
+
+ ))
+ }
+
+ ,
+ );
+
+ expect(errorSpy).toHaveBeenCalledWith(
+ 'Warning: `preserve` should not apply on Form.List fields.',
+ );
+
+ errorSpy.mockRestore();
+ });
});
/* eslint-enable no-template-curly-in-string */