Skip to content

Commit 5660128

Browse files
authored
chore: Update deps test case and logic (#7)
* adjust deps logic * update demo * adjust deps logic * update test case
1 parent ac52393 commit 5660128

File tree

7 files changed

+80
-10
lines changed

7 files changed

+80
-10
lines changed

examples/StateForm-basic.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ export default class Demo extends React.Component {
3838
<Field dependencies={['username']}>
3939
{(control, meta, context) => {
4040
const { username } = context.getFieldsValue();
41-
return username === '111' ? <Input {...control} placeholder="I am secret!" /> : null;
41+
console.log('my render!', username);
42+
return username === '111' && <Input {...control} placeholder="I am secret!" />;
4243
}}
4344
</Field>
4445

src/Field.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
169169
break;
170170
}
171171

172+
case 'dependenciesUpdate': {
173+
/**
174+
* Trigger when marked `dependencies` updated. Related fields will all update
175+
*/
176+
const dependencyList = dependencies.map(getNamePath);
177+
if (
178+
(namePathList && containsNamePath(namePathList, namePath)) ||
179+
dependencyList.some(dependency => containsNamePath(info.relatedFields, dependency))
180+
) {
181+
this.forceUpdate();
182+
}
183+
break;
184+
}
185+
172186
default:
173187
/**
174188
* - If `namePath` exists in `namePathList`, means it's related value and should update.

src/interface.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ export type NotifyInfo =
9797
| {
9898
type: 'setField';
9999
data: FieldData;
100+
}
101+
| {
102+
type: 'dependenciesUpdate';
103+
/**
104+
* Contains all the related `InternalNamePath[]`.
105+
* a <- b <- c : change `a`
106+
* relatedFields=[a, b, c]
107+
*/
108+
relatedFields: InternalNamePath[];
100109
};
101110

102111
export interface Callbacks {

src/useForm.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ export class FormStore {
316316
const childrenFields = this.getDependencyChildrenFields(namePath);
317317
this.validateFields(childrenFields);
318318

319+
this.notifyObservers(prevStore, childrenFields, {
320+
type: 'dependenciesUpdate',
321+
relatedFields: [namePath, ...childrenFields],
322+
});
323+
319324
// trigger callback function
320325
const { onValuesChange } = this.callbacks;
321326

tests/common/InfoField.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@ interface InfoFieldProps extends FieldProps {
66
children: ReactElement;
77
}
88

9+
export const Input = ({ value = '', ...props }) => <input {...props} value={value} />;
10+
911
/**
1012
* Return a wrapped Field with meta info
1113
*/
1214
const InfoField: React.FC<InfoFieldProps> = ({ children, ...props }) => (
1315
<Field {...props}>
1416
{(control, { errors }) => (
1517
<div>
16-
{children ? (
17-
React.cloneElement(children, control)
18-
) : (
19-
<input {...control} value={control.value || ''} />
20-
)}
18+
{children ? React.cloneElement(children, control) : <Input {...control} />}
2119
<ul className="errors">
2220
{errors.map(error => (
2321
<li key={error}>{error}</li>

tests/common/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import timeout from './timeout';
2-
import InfoField from './InfoField';
2+
import InfoField, { Input } from './InfoField';
33

44
export async function changeValue(wrapper, value) {
55
wrapper.find('input').simulate('change', { target: { value } });
@@ -22,3 +22,7 @@ export function matchError(wrapper, error) {
2222
export function getField(wrapper, index = 0) {
2323
return wrapper.find(InfoField).at(index);
2424
}
25+
26+
export function getInput(wrapper, index = 0) {
27+
return wrapper.find(Input).at(index);
28+
}

tests/dependencies.test.js

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3-
import Form from '../src';
4-
import InfoField from './common/InfoField';
5-
import { changeValue, matchError, getField } from './common';
3+
import Form, { Field } from '../src';
4+
import InfoField, { Input } from './common/InfoField';
5+
import { changeValue, matchError, getField, getInput } from './common';
66

77
describe('dependencies', () => {
88
it('touched', async () => {
@@ -30,4 +30,43 @@ describe('dependencies', () => {
3030
await changeValue(getField(wrapper, 0), '');
3131
matchError(getField(wrapper, 1), true);
3232
});
33+
34+
it('nest dependencies', async () => {
35+
let form = null;
36+
let rendered = false;
37+
38+
const wrapper = mount(
39+
<div>
40+
<Form
41+
ref={instance => {
42+
form = instance;
43+
}}
44+
>
45+
<Field name="field_1">
46+
<Input />
47+
</Field>
48+
<Field name="field_2" dependencies={['field_1']}>
49+
<Input />
50+
</Field>
51+
<Field name="field_3" dependencies={['field_2']}>
52+
{control => {
53+
rendered = true;
54+
return <Input {...control} />;
55+
}}
56+
</Field>
57+
</Form>
58+
</div>,
59+
);
60+
61+
form.setFields([
62+
{ name: 'field_1', touched: true },
63+
{ name: 'field_2', touched: true },
64+
{ name: 'field_3', touched: true },
65+
]);
66+
67+
rendered = false;
68+
await changeValue(getInput(wrapper), '1');
69+
70+
expect(rendered).toBeTruthy();
71+
});
3372
});

0 commit comments

Comments
 (0)