Skip to content

Commit 20fa46c

Browse files
authored
fix: preserve should back to initialValues (#255)
* docs: Add test example * test: Update test case * fix lint * fix: keep logic
1 parent 0a3beac commit 20fa46c

File tree

10 files changed

+117
-4
lines changed

10 files changed

+117
-4
lines changed

.eslintrc.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ module.exports = {
1515
'jsx-a11y/label-has-associated-control': 0,
1616
'import/no-extraneous-dependencies': 0,
1717
'import/no-unresolved': 0,
18+
'@typescript-eslint/no-redeclare': 0,
19+
'@typescript-eslint/method-signature-style': 0,
20+
'no-async-promise-executor': 0,
1821
},
1922
};

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
/es
1414
/lib
1515
.doc
16+
/coverage
1617

1718
# misc
1819
.DS_Store

docs/demo/deps.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## deps
2+
3+
4+
<code src="../examples/deps.tsx" />

docs/demo/preserve.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## preserve
2+
3+
4+
<code src="../examples/preserve.tsx" />

docs/examples/preserve.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable react/prop-types */
2+
3+
import React from 'react';
4+
import Form from 'rc-field-form';
5+
import Input from './components/Input';
6+
7+
const { Field } = Form;
8+
9+
export default () => {
10+
const [form] = Form.useForm();
11+
12+
return (
13+
<Form
14+
form={form}
15+
initialValues={{ test: 'bamboo' }}
16+
onFinish={values => {
17+
console.log('Submit:', values);
18+
}}
19+
>
20+
<Field shouldUpdate>
21+
{() => (
22+
<>
23+
<Field name="test" preserve={false}>
24+
<Input />
25+
</Field>
26+
{/* <Field name="test">
27+
<Input />
28+
</Field> */}
29+
</>
30+
)}
31+
</Field>
32+
<button type="submit">Submit</button>
33+
<button
34+
type="button"
35+
onClick={() => {
36+
form.resetFields();
37+
}}
38+
>
39+
Reset
40+
</button>
41+
</Form>
42+
);
43+
};

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,13 @@
5959
"@types/lodash": "^4.14.135",
6060
"@types/react": "^16.8.19",
6161
"@types/react-dom": "^16.8.4",
62+
"@umijs/fabric": "^2.5.2",
6263
"@umijs/test": "^3.2.27",
6364
"dumi": "^1.1.0",
6465
"enzyme": "^3.1.0",
6566
"enzyme-adapter-react-16": "^1.0.2",
6667
"enzyme-to-json": "^3.1.4",
68+
"eslint": "^7.18.0",
6769
"father": "^2.13.6",
6870
"father-build": "^1.18.6",
6971
"gh-pages": "^3.1.0",

src/Field.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
386386

387387
public isList = () => this.props.isList;
388388

389+
public isPreserve = () => this.props.preserve;
390+
389391
// ============================= Child Component =============================
390392
public getMeta = (): Meta => {
391393
// Make error & validating in cache to save perf

src/interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export interface FieldEntity {
9999
isFieldValidating: () => boolean;
100100
isListField: () => boolean;
101101
isList: () => boolean;
102+
isPreserve: () => boolean;
102103
validateRules: (options?: ValidateOptions) => Promise<string[]>;
103104
getMeta: () => Meta;
104105
getNamePath: () => InternalNamePath;

src/useForm.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
containsNamePath,
3131
getNamePath,
3232
getValue,
33+
matchNamePath,
3334
setValue,
3435
setValues,
3536
} from './utils/valueUtil';
@@ -542,8 +543,18 @@ export class FormStore {
542543
const mergedPreserve = preserve !== undefined ? preserve : this.preserve;
543544
if (mergedPreserve === false && !isListField) {
544545
const namePath = entity.getNamePath();
545-
if (namePath.length && this.getFieldValue(namePath) !== undefined) {
546-
this.store = setValue(this.store, namePath, undefined);
546+
const defaultValue = getValue(this.initialValues, namePath);
547+
548+
if (
549+
namePath.length &&
550+
this.getFieldValue(namePath) !== defaultValue &&
551+
this.fieldEntities.every(
552+
field =>
553+
// Only reset when no namePath exist
554+
!matchNamePath(field.getNamePath(), namePath),
555+
)
556+
) {
557+
this.store = setValue(this.store, namePath, defaultValue);
547558
}
548559
}
549560
};

tests/preserve.test.tsx

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('Form.Preserve', () => {
3737

3838
await matchTest(false, { keep: 233, remove: 666 });
3939
await matchTest(true, { keep: 233 });
40-
await matchTest(false, { keep: 233 });
40+
await matchTest(false, { keep: 233, remove: 666 });
4141
});
4242

4343
it('form', async () => {
@@ -54,7 +54,49 @@ describe('Form.Preserve', () => {
5454

5555
await matchTest(false, { keep: 233, remove: 666 });
5656
await matchTest(true, { keep: 233 });
57-
await matchTest(false, { keep: 233 });
57+
await matchTest(false, { keep: 233, remove: 666 });
58+
});
59+
60+
it('keep preserve when other field exist the name', async () => {
61+
const formRef = React.createRef<FormInstance>();
62+
63+
const KeepDemo = ({ onFinish, keep }: { onFinish: (values: any) => void; keep: boolean }) => {
64+
return (
65+
<Form ref={formRef} initialValues={{ test: 'bamboo' }} onFinish={onFinish}>
66+
<Form.Field shouldUpdate>
67+
{() => {
68+
return (
69+
<>
70+
{keep && <InfoField name="test" preserve={false} />}
71+
<InfoField name="test" />
72+
</>
73+
);
74+
}}
75+
</Form.Field>
76+
</Form>
77+
);
78+
};
79+
80+
const onFinish = jest.fn();
81+
const wrapper = mount(<KeepDemo onFinish={onFinish} keep />);
82+
83+
// Change value
84+
wrapper
85+
.find('input')
86+
.first()
87+
.simulate('change', { target: { value: 'light' } });
88+
89+
formRef.current.submit();
90+
await timeout();
91+
expect(onFinish).toHaveBeenCalledWith({ test: 'light' });
92+
onFinish.mockReset();
93+
94+
// Remove preserve should not change the value
95+
wrapper.setProps({ keep: false });
96+
await timeout();
97+
formRef.current.submit();
98+
await timeout();
99+
expect(onFinish).toHaveBeenCalledWith({ test: 'light' });
58100
});
59101

60102
it('form perishable but field !perishable', async () => {

0 commit comments

Comments
 (0)