Skip to content

Commit 1f773ed

Browse files
authored
fix: Form preserve should not clear when top level need keep (#442)
* test: test dricen * fix: perserve logic
1 parent eb07427 commit 1f773ed

File tree

3 files changed

+89
-46
lines changed

3 files changed

+89
-46
lines changed

docs/examples/basic.tsx

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,40 @@ import Input from './components/Input';
44

55
export default () => {
66
const [form] = Form.useForm();
7+
const [show, setShow] = React.useState(true);
8+
const [timeoutShow, setTimeoutShow] = React.useState(show);
79

8-
return (
9-
<Form form={form} preserve={false}>
10-
<Field name="name">
11-
<Input placeholder="Username" />
12-
</Field>
10+
React.useEffect(() => {
11+
if (show) {
12+
console.log(
13+
'show',
14+
);
15+
form.setFieldsValue({
16+
name: '123',
17+
});
18+
}
19+
20+
const id = setTimeout(() =>{
21+
setTimeoutShow(show);
22+
}, 300);
23+
24+
return () => clearTimeout(id);
25+
}, [show]);
1326

14-
<Field dependencies={['name']}>
15-
{() => {
16-
return form.getFieldValue('name') === '1' ? (
17-
<Field name="password">
18-
<Input placeholder="Password" />
19-
</Field>
20-
) : null;
21-
}}
22-
</Field>
2327

24-
<Field dependencies={['password']}>
25-
{() => {
26-
const password = form.getFieldValue('password');
27-
console.log('>>>', password);
28-
return password ? (
29-
<Field name="password2">
30-
<Input placeholder="Password 2" />
31-
</Field>
32-
) : null;
33-
}}
34-
</Field>
35-
</Form>
28+
29+
return (
30+
<>
31+
<button onClick={() =>{
32+
setShow(!show);
33+
}}>Trigger</button>
34+
{
35+
timeoutShow && <Form form={form}>
36+
<Form.Field name="name">
37+
<Input />
38+
</Form.Field>
39+
</Form>
40+
}
41+
</>
3642
);
3743
};

src/useForm.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
1-
import * as React from 'react';
21
import warning from 'rc-util/lib/warning';
2+
import * as React from 'react';
3+
import { HOOK_MARK } from './FieldContext';
34
import type {
45
Callbacks,
56
FieldData,
67
FieldEntity,
78
FieldError,
8-
InternalNamePath,
9+
FormInstance,
10+
InternalFieldData,
11+
InternalFormInstance,
912
InternalHooks,
13+
InternalNamePath,
14+
InternalValidateFields,
15+
Meta,
1016
NamePath,
1117
NotifyInfo,
18+
RuleError,
1219
Store,
13-
ValidateOptions,
14-
FormInstance,
15-
ValidateMessages,
16-
InternalValidateFields,
17-
InternalFormInstance,
18-
ValidateErrorEntity,
1920
StoreValue,
20-
Meta,
21-
InternalFieldData,
21+
ValidateErrorEntity,
22+
ValidateMessages,
23+
ValidateOptions,
2224
ValuedNotifyInfo,
23-
RuleError,
2425
WatchCallBack,
2526
} from './interface';
26-
import { HOOK_MARK } from './FieldContext';
2727
import { allPromiseFinish } from './utils/asyncUtil';
28-
import NameMap from './utils/NameMap';
28+
import cloneDeep from './utils/cloneDeep';
2929
import { defaultValidateMessages } from './utils/messages';
30+
import NameMap from './utils/NameMap';
3031
import {
3132
cloneByNamePathList,
3233
containsNamePath,
@@ -36,7 +37,6 @@ import {
3637
setValue,
3738
setValues,
3839
} from './utils/valueUtil';
39-
import cloneDeep from './utils/cloneDeep';
4040

4141
type InvalidateFieldEntity = { INVALIDATE_NAME_PATH: InternalNamePath };
4242

@@ -157,7 +157,7 @@ export class FormStore {
157157
private destroyForm = () => {
158158
const prevWithoutPreserves = new NameMap<boolean>();
159159
this.getFieldEntities(true).forEach(entity => {
160-
if (!entity.isPreserve()) {
160+
if (!this.isMergedPreserve(entity.isPreserve())) {
161161
prevWithoutPreserves.set(entity.getNamePath(), true);
162162
}
163163
});
@@ -604,6 +604,11 @@ export class FormStore {
604604
}
605605
};
606606

607+
private isMergedPreserve = (fieldPreserve?: boolean) => {
608+
const mergedPreserve = fieldPreserve !== undefined ? fieldPreserve : this.preserve;
609+
return mergedPreserve ?? true;
610+
};
611+
607612
private registerField = (entity: FieldEntity) => {
608613
this.fieldEntities.push(entity);
609614
const namePath = entity.getNamePath();
@@ -622,10 +627,9 @@ export class FormStore {
622627
// un-register field callback
623628
return (isListField?: boolean, preserve?: boolean, subNamePath: InternalNamePath = []) => {
624629
this.fieldEntities = this.fieldEntities.filter(item => item !== entity);
625-
// Clean up store value if not preserve
626-
const mergedPreserve = preserve !== undefined ? preserve : this.preserve;
627630

628-
if (mergedPreserve === false && (!isListField || subNamePath.length > 1)) {
631+
// Clean up store value if not preserve
632+
if (!this.isMergedPreserve(preserve) && (!isListField || subNamePath.length > 1)) {
629633
const defaultValue = isListField ? undefined : this.getInitialValue(namePath);
630634

631635
if (

tests/preserve.test.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable no-template-curly-in-string, arrow-body-style */
2-
import React from 'react';
32
import { mount } from 'enzyme';
4-
import Form, { FormInstance } from '../src';
3+
import React from 'react';
4+
import type { FormInstance } from '../src';
5+
import Form from '../src';
56
import InfoField, { Input } from './common/InfoField';
67
import timeout from './common/timeout';
78

@@ -438,5 +439,37 @@ describe('Form.Preserve', () => {
438439
expect(wrapper.exists('#password2')).toBeFalsy();
439440
});
440441
});
442+
443+
it('should correct calculate preserve state', () => {
444+
let instance: FormInstance;
445+
446+
const VisibleDemo = ({ visible = true }: { visible?: boolean }) => {
447+
const [form] = Form.useForm();
448+
instance = form;
449+
450+
return visible ? (
451+
<Form form={form}>
452+
<Form.Field name="name">
453+
<Input />
454+
</Form.Field>
455+
</Form>
456+
) : (
457+
<div />
458+
);
459+
};
460+
461+
const wrapper = mount(<VisibleDemo />);
462+
463+
wrapper.setProps({
464+
visible: false,
465+
});
466+
467+
instance.setFieldsValue({ name: 'bamboo' });
468+
wrapper.setProps({
469+
visible: true,
470+
});
471+
472+
expect(wrapper.find('input').prop('value')).toEqual('bamboo');
473+
});
441474
});
442475
/* eslint-enable no-template-curly-in-string */

0 commit comments

Comments
 (0)