FormModal
传统问题:
1、弹窗关闭时数据会清空,下一次打开数据还在
2、写一个弹窗、需要创建一堆变量,如 visible、loading、onClose、onOk…
3、开发者需要关注的副作用多,如打开/关闭弹窗、保存成功后刷新列表
4、编辑时回显数据逻辑、保存逻辑重复代码过多
解决方案
const FormModal = props => {
const {onRef, onSave, onEcho, onSuccessCallback, children} = props;
const [open, setOpen] = useState(false);
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const onClose = () => {
setOpen(false);
};
const valid = async () => {
try {
return await form.validateFields();
} catch (e) {
return false;
}
};
const onOk = async () => {
try {
const formValue = await valid();
if (!formValue) return;
setLoading(true);
const msg = await onSave(formValue, data);
setLoading(false);
message.success(msg || '操作成功');
onClose();
onSuccessCallback?.();
} catch (e) {
message.error(e?.message || '操作失败');
setLoading(false);
}
};
useImperativeHandle(onRef, () => ({
open(value = null) {
setData(value);
setOpen(true);
},
}));
/*
* 回显加载数据
* */
useEffect(() => {
if (data && onEcho) {
setLoading(true);
onEcho(data)
.then(value => {
form.setFieldsValue(value);
})
.catch(e => {
onClose();
message.error(e?.message || '数据回显失败');
})
.finally(() => {
setLoading(false);
});
}
}, [data]);
/*
* 处理关闭弹窗副作用
* */
useEffect(() => {
if (!open) {
form.resetFields();
setData(null);
}
}, [open]);
return (
<Modal
confirmLoading={loading}
maskClosable={false}
closable={false}
open={open}
onOk={onOk}
onCancel={onClose}
styles={{
footer: {display: 'flex', justifyContent: 'center', gap: 30},
}}>
<Spin spinning={loading} tip="Loading">
<Form form={form}>{children}</Form>
</Spin>
</Modal>
);
};
使用
const BizModal = props => {
const {onRef} = props;
const onEcho = async params => {
const res = await fetchData(params);
return res.data;//需和表单字段一致
};
const onSave = async value => {
const res = await fetchData(value);
return res.msg;//返回成功提示信息即可
};
return (
<FormModal onRef={onRef} onSave={onSave} onEcho={onEcho}>
<Form.Item
label="姓名"
name="username"
rules={[{required: true, message: '请输入姓名'}]}>
<Input />
</Form.Item>
</FormModal>
);
};