Skip to content

Commit 16e639d

Browse files
committed
feat: Form context nest support
1 parent 6e54eb5 commit 16e639d

File tree

3 files changed

+67
-29
lines changed

3 files changed

+67
-29
lines changed

src/Form.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ const Form: React.FunctionComponent<FormProps> = (
6262
React.useImperativeHandle(ref, () => formInstance);
6363

6464
// Register form into Context
65-
React.useEffect(() => formContext.registerForm(name, formInstance), [
66-
formContext,
67-
formInstance,
68-
name,
69-
]);
65+
React.useEffect(() => {
66+
formContext.registerForm(name, formInstance);
67+
return () => {
68+
formContext.unregisterForm(name);
69+
};
70+
}, [formContext, formInstance, name]);
7071

7172
// Pass props to store
7273
setValidateMessages({

src/FormContext.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ export interface FormProviderProps {
1717

1818
export interface FormContextProps extends FormProviderProps {
1919
triggerFormChange: (name: string, changedFields: FieldData[]) => void;
20-
registerForm: (name: string, form: FormInstance) => () => void;
20+
registerForm: (name: string, form: FormInstance) => void;
21+
unregisterForm: (name: string) => void;
2122
}
2223

2324
const FormContext = React.createContext<FormContextProps>({
2425
triggerFormChange: () => {},
25-
registerForm: () => () => {},
26+
registerForm: () => {},
27+
unregisterForm: () => {},
2628
});
2729

2830
const FormProvider: React.FunctionComponent<FormProviderProps> = ({
@@ -38,7 +40,7 @@ const FormProvider: React.FunctionComponent<FormProviderProps> = ({
3840
<FormContext.Provider
3941
value={{
4042
...formContext,
41-
validateMessages,
43+
validateMessages: { ...formContext.validateMessages, ...validateMessages },
4244

4345
// =========================================================
4446
// = Global Form Control =
@@ -50,6 +52,8 @@ const FormProvider: React.FunctionComponent<FormProviderProps> = ({
5052
forms: formsRef.current,
5153
});
5254
}
55+
56+
formContext.triggerFormChange(name, changedFields);
5357
},
5458
registerForm: (name, form) => {
5559
if (name) {
@@ -59,11 +63,14 @@ const FormProvider: React.FunctionComponent<FormProviderProps> = ({
5963
};
6064
}
6165

62-
return () => {
63-
const newForms = { ...formsRef.current };
64-
delete newForms[name];
65-
formsRef.current = newForms;
66-
};
66+
formContext.registerForm(name, form);
67+
},
68+
unregisterForm: name => {
69+
const newForms = { ...formsRef.current };
70+
delete newForms[name];
71+
formsRef.current = newForms;
72+
73+
formContext.unregisterForm(name);
6774
},
6875
}}
6976
>

tests/context.test.js

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,56 @@ describe('Form.Context', () => {
4343
);
4444
});
4545

46-
it('adjust sub form', async () => {
47-
const onFormChange = jest.fn();
46+
describe('adjust sub form', () => {
47+
it('basic', async () => {
48+
const onFormChange = jest.fn();
4849

49-
const wrapper = mount(
50-
<FormProvider onFormChange={onFormChange}>
51-
<Form name="form1" />
52-
</FormProvider>,
53-
);
50+
const wrapper = mount(
51+
<FormProvider onFormChange={onFormChange}>
52+
<Form name="form1" />
53+
</FormProvider>,
54+
);
5455

55-
wrapper.setProps({
56-
children: (
57-
<Form name="form2">
58-
<InfoField name="test" />
59-
</Form>
60-
),
56+
wrapper.setProps({
57+
children: (
58+
<Form name="form2">
59+
<InfoField name="test" />
60+
</Form>
61+
),
62+
});
63+
64+
await changeValue(getField(wrapper), 'Bamboo');
65+
const { forms } = onFormChange.mock.calls[0][1];
66+
expect(Object.keys(forms)).toEqual(['form2']);
6167
});
6268

63-
await changeValue(getField(wrapper), 'Bamboo');
64-
const { forms } = onFormChange.mock.calls[0][1];
65-
expect(Object.keys(forms)).toEqual(['form2']);
69+
it('multiple context', async () => {
70+
const onFormChange = jest.fn();
71+
72+
const Demo = changed => (
73+
<FormProvider onFormChange={onFormChange}>
74+
<FormProvider>
75+
{!changed ? (
76+
<Form name="form1" />
77+
) : (
78+
<Form name="form2">
79+
<InfoField name="test" />
80+
</Form>
81+
)}
82+
</FormProvider>
83+
</FormProvider>
84+
);
85+
86+
const wrapper = mount(<Demo />);
87+
88+
wrapper.setProps({
89+
changed: true,
90+
});
91+
92+
await changeValue(getField(wrapper), 'Bamboo');
93+
const { forms } = onFormChange.mock.calls[0][1];
94+
expect(Object.keys(forms)).toEqual(['form2']);
95+
});
6696
});
6797

6898
it('do nothing if no Provider in use', () => {

0 commit comments

Comments
 (0)