Skip to content

Commit

Permalink
fix(form): fix the problem of multiple calls (#3676)
Browse files Browse the repository at this point in the history
* fix(form): fix the problem of multiple calls

* add more test

* fix test
  • Loading branch information
chenshuai2144 authored Sep 15, 2021
1 parent ee0f5f4 commit cd43748
Show file tree
Hide file tree
Showing 14 changed files with 139 additions and 61 deletions.
5 changes: 4 additions & 1 deletion packages/form/src/BaseForm/createField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 180,10 @@ function createField<P extends ProFormFieldItemProps = any>(
</ProFormItem>
);
};

// 标记是否是 proform 的组件
// @ts-ignore
// eslint-disable-next-line no-param-reassign
FieldWithContext.displayName = 'ProFormComponent';
return FieldWithContext as ProFormComponent<P, ExtendsProps>;
}

Expand Down
3 changes: 3 additions & 0 deletions packages/form/src/components/DatePicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 15,8 @@ ExportComponent.Week = ProFormDatePickerWeek;
ExportComponent.Month = ProFormDatePickerMonth;
ExportComponent.Quarter = ProFormDatePickerQuarter;
ExportComponent.Year = ProFormDatePickerYear;
// @ts-ignore
// eslint-disable-next-line no-param-reassign
ExportComponent.displayName = 'ProFormComponent';

export default ExportComponent;
8 changes: 1 addition & 7 deletions packages/form/src/components/Field/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 73,7 @@ const ProFormField: React.FC<
render={render as any}
renderFormItem={renderFormItem as any}
valueType={(valueType as 'text') || 'text'}
fieldProps={{
...fieldProps,
onChange: (...restParams: any) => {
(fieldProps?.onChange as any)?.(...restParams);
onChange?.(...restParams);
},
}}
fieldProps={fieldProps}
valueEnum={runFunction(valueEnum)}
{...proFieldProps}
{...restProps}
Expand Down
59 changes: 39 additions & 20 deletions packages/form/src/components/FieldSet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 32,50 @@ const FieldSet: React.FC<ProFormFieldSetProps> = ({
value = [],
valuePropName,
onChange,
fieldProps,
space,
type = 'space',
}) => {
const fieldSetOnChange = (fileValue: any, index: number) => {
const newValues = [...value];
newValues[index] = defaultGetValueFromEvent(valuePropName || 'value', fileValue);
onChange?.(newValues);
fieldProps?.onChange?.(newValues);
};

let itemIndex = -1;
const list = toArray(children).map((item: any) => {
if (React.isValidElement(item)) {
itemIndex = 1;
const index = itemIndex;
return React.cloneElement(item, {
key: index,
ignoreFormItem: true,
...((item.props as any) || {}),
fieldProps: {
...(item?.props as any)?.fieldProps,
onChange: (...restParams: any) => {
(item.props as any)?.fieldProps?.onChange?.(...restParams);
(item.props as any)?.onChange?.(...restParams);
fieldSetOnChange(restParams[0], index);
},
},
value: value[index],
onChange: (itemValue: any) => {
fieldSetOnChange(itemValue, index);
(item as any).props.onChange?.(itemValue);
},
});
const isProFromItem =
// @ts-ignore
item?.type?.displayName === 'ProFormComponent' || item?.props?.readonly;
const forkProps = isProFromItem
? {
key: index,
ignoreFormItem: true,
...((item.props as any) || {}),
// 如果不是我们自定义的组件 fieldProps 无法识别
fieldProps: {
...(item?.props as any)?.fieldProps,
onChange: (...restParams: any) => {
fieldSetOnChange(restParams[0], index);
},
},
value: value[index],
onChange: undefined,
}
: {
key: index,
...((item.props as any) || {}),
value: value[index],
onChange: (itemValue: any) => {
fieldSetOnChange(itemValue, index);
(item as any).props.onChange?.(itemValue);
},
};
return React.cloneElement(item, forkProps);
}
return item;
});
Expand All @@ -72,7 84,7 @@ const FieldSet: React.FC<ProFormFieldSetProps> = ({
/** Input.Group 需要配置 compact */
const typeProps = { ...(type === 'group' ? { compact: true } : {}) };
return (
<Components {...typeProps} {...(space as SpaceProps)}>
<Components {...typeProps} {...(space as SpaceProps)} align="start">
{list}
</Components>
);
Expand All @@ -82,7 94,14 @@ const ProFormFieldSet: React.FC<FormItemProps & ProFormFieldSetProps> = React.fo
({ children, space, valuePropName, ...rest }, ref) => {
useImperativeHandle(ref, () => {}, []);
return (
<FieldSet space={space} valuePropName={valuePropName} {...rest.fieldProps} {...rest}>
<FieldSet
space={space}
valuePropName={valuePropName}
{...rest.fieldProps}
// 把 fieldProps 里的重置掉
onChange={undefined}
{...rest}
>
{children}
</FieldSet>
);
Expand Down
14 changes: 10 additions & 4 deletions packages/form/src/components/FormItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 26,7 @@ const WithValueFomFiledProps: React.FC<Record<string, any>> = (formFieldProps) =
value,
onChange,
onBlur,
ignoreFormItem,
valuePropName = 'value',
...restProps
} = formFieldProps;
Expand Down Expand Up @@ -58,16 59,20 @@ const WithValueFomFiledProps: React.FC<Record<string, any>> = (formFieldProps) =

if (!React.isValidElement(filedChildren)) return filedChildren as JSX.Element;

const finalChange = fieldProps
? undefined
: (...restParams: any[]) => {
onChange?.(...restParams);
filedChildren?.props?.onChange?.(...restParams);
};

return React.cloneElement(
filedChildren,
omitUndefined({
...restProps,
value,
...filedChildren.props,
onChange: (...restParams: any[]) => {
onChange?.(...restParams);
filedChildren?.props?.onChange?.(...restParams);
},
onChange: finalChange,
fieldProps,
}),
);
Expand Down Expand Up @@ -215,6 220,7 @@ const ProFormItem: React.FC<ProFormItemProps> = (props) => {
if (ignoreFormItem) {
return <>{lightDom}</>;
}

return (
<WarpFormItem {...rest} name={name}>
{lightDom}
Expand Down
4 changes: 4 additions & 0 deletions packages/form/src/components/Radio/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 67,8 @@ WrappedProFormRadio.Group = RadioGroup;

WrappedProFormRadio.Button = Radio.Button;

// @ts-ignore
// eslint-disable-next-line no-param-reassign
WrappedProFormRadio.displayName = 'ProFormComponent';

export default WrappedProFormRadio;
8 changes: 1 addition & 7 deletions packages/form/src/components/Rate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 15,7 @@ const ProFormRate: React.ForwardRefRenderFunction<any, ProFormFieldItemProps<Rat
<ProField
valueType="rate"
mode="edit"
fieldProps={{
...fieldProps,
onChange: (...restParams: any) => {
(fieldProps?.onChange as any)?.(...restParams);
(rest as any)?.onChange?.(...restParams);
},
}}
fieldProps={fieldProps}
ref={ref}
proFieldProps={proFieldProps}
filedConfig={{
Expand Down
2 changes: 1 addition & 1 deletion packages/form/src/components/SchemaForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 235,7 @@ function BetaSchemaForm<T, ValueType = 'text'>(props: FormSchema<T, ValueType>)

/** 分割线 */
if (item.valueType === 'divider') {
return <Divider {...item.fieldProps} />;
return <Divider {...item.fieldProps} key={index} />;
}

/** 公用的 类型 props */
Expand Down
4 changes: 4 additions & 0 deletions packages/form/src/components/Select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 130,8 @@ const WrappedProFormSelect = ProFormSelect as (<T = any>(

WrappedProFormSelect.SearchSelect = ProFormSearchSelect;

// @ts-ignore
// eslint-disable-next-line no-param-reassign
WrappedProFormSelect.displayName = 'ProFormComponent';

export default WrappedProFormSelect;
12 changes: 5 additions & 7 deletions packages/form/src/components/Text/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 19,7 @@ const ProFormText: React.FC<ProFormFieldItemProps<InputProps>> = ({
<ProField
mode="edit"
valueType={valueType}
fieldProps={{
...fieldProps,
onChange: (...restParams: any) => {
(fieldProps?.onChange as any)?.(...restParams);
(rest as any)?.onChange?.(...restParams);
},
}}
fieldProps={fieldProps}
filedConfig={
{
valueType,
Expand Down Expand Up @@ -64,4 58,8 @@ const WrappedProFormText: typeof ProFormText & {

WrappedProFormText.Password = Password;

// @ts-ignore
// eslint-disable-next-line no-param-reassign
WrappedProFormText.displayName = 'ProFormComponent';

export default WrappedProFormText;
8 changes: 1 addition & 7 deletions packages/form/src/components/TextArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 17,7 @@ const ProFormTextArea: React.ForwardRefRenderFunction<any, ProFormFieldItemProps
ref={ref}
mode="edit"
valueType="textarea"
fieldProps={{
...fieldProps,
onChange: (...restParams: any) => {
(fieldProps?.onChange as any)?.(...restParams);
(rest as any)?.onChange?.(...restParams);
},
}}
fieldProps={fieldProps}
proFieldProps={proFieldProps}
{...rest}
/>
Expand Down
12 changes: 6 additions & 6 deletions tests/form/__snapshots__/demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2780,7 2780,7 @@ exports[`form demos 📸 renders ./packages/form/src/components/FieldSet/demos/c
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center"
class="ant-space ant-space-horizontal ant-space-align-start"
>
<div
class="ant-space-item"
Expand Down Expand Up @@ -4731,7 4731,7 @@ exports[`form demos 📸 renders ./packages/form/src/components/FieldSet/demos/f
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center"
class="ant-space ant-space-horizontal ant-space-align-start"
>
<div
class="ant-space-item"
Expand Down Expand Up @@ -5064,7 5064,7 @@ exports[`form demos 📸 renders ./packages/form/src/components/FieldSet/demos/f
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center"
class="ant-space ant-space-horizontal ant-space-align-start"
>
<div
class="ant-space-item"
Expand Down Expand Up @@ -9512,7 9512,7 @@ Array [
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center"
class="ant-space ant-space-horizontal ant-space-align-start"
>
<div
class="ant-space-item"
Expand Down Expand Up @@ -19092,7 19092,7 @@ Array [
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center"
class="ant-space ant-space-horizontal ant-space-align-start"
>
<div
class="ant-space-item"
Expand Down Expand Up @@ -20273,7 20273,7 @@ exports[`form demos 📸 renders ./packages/form/src/components/SchemaForm/demos
class="ant-form-item-control-input-content"
>
<div
class="ant-space ant-space-horizontal ant-space-align-center"
class="ant-space ant-space-horizontal ant-space-align-start"
>
<div
class="ant-space-item"
Expand Down
59 changes: 59 additions & 0 deletions tests/form/fieldSet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 8,7 @@ import ProForm, {
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { waitForComponentToPaint } from '../util';
import { Input } from 'antd';

describe('ProFormFieldSet', () => {
it('😊 ProFormFieldSet onChange', async () => {
Expand Down Expand Up @@ -45,7 46,65 @@ describe('ProFormFieldSet', () => {
});
await waitForComponentToPaint(html);
expect(valueFn).toBeCalledWith(['111']);
expect(valueFn).toBeCalledTimes(1);
act(() => {
html.find('textarea#filedSet3').simulate('change', {
target: {
value: '333',
},
});
});
await waitForComponentToPaint(html);
expect(valueFn).toBeCalledWith(['111', undefined, '333']);

act(() => {
html.find('li > div').at(1).simulate('click');
});
expect(valueFn).toBeCalledWith(['111', 2, '333']);
await waitForComponentToPaint(html);

await waitForComponentToPaint(html, 200);

act(() => {
html.find('button.ant-btn.ant-btn-primary').simulate('click');
});
await waitForComponentToPaint(html, 200);

expect(fn).toBeCalledWith(['111', 2, '333']);
html.unmount();
});

it('😊 ProFormFieldSet support Input onChange', async () => {
const fn = jest.fn();
const valueFn = jest.fn();
const html = mount(
<ProForm
onFinish={(values) => fn(values.list)}
onValuesChange={(value) => valueFn(value.list)}
>
<ProFormFieldSet name="list">
<Input id="filedSet1" key="filedSet1" />
<ProFormRate key="filedSet2" />
<ProFormTextArea
fieldProps={{
id: 'filedSet3',
}}
key="filedSet3"
/>
</ProFormFieldSet>
</ProForm>,
);

act(() => {
html.find('input#filedSet1').simulate('change', {
target: {
value: '111',
},
});
});
await waitForComponentToPaint(html);
expect(valueFn).toBeCalledWith(['111']);
expect(valueFn).toBeCalledTimes(1);
act(() => {
html.find('textarea#filedSet3').simulate('change', {
target: {
Expand Down
2 changes: 1 addition & 1 deletion tests/form/formitem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 37,7 @@ describe('ProForm.Item', () => {
expect(onBlur).toBeCalledTimes(1);
});

it('📦 ProForm.Item supprot onChange', async () => {
it('📦 ProForm.Item supports onChange', async () => {
const onChange = jest.fn();
const onValuesChange = jest.fn();
const wrapper = mount<{ navTheme: string }>(
Expand Down

0 comments on commit cd43748

Please sign in to comment.