《React HOC》异步引入定制化的Antd Modal组件
使用场景
点击按钮时(或者其他触发时机),异步加载你的Modal组件,可以实现将Modal组件逻辑与主页面逻辑分开维护。
实现
以Antd的Modal为例。
withShowModal.jsx
核心逻辑
// import { ModalProps, Modal } from 'antd';
import React from 'react';
import {
createPortal,
render as reactRender,
unmountComponentAtNode as reactUnmount,
} from 'react-dom';
export function withShowModal(Element) {
function InnerElement(props) {
return <Element {...props} />;
}
function show(config, targetDom) {
const container = targetDom || document.getElementById('root') || document.body;
const renderDom = document.createDocumentFragment();
function render(props) {
// reactRender(<InnerElement {...props} />, container);
reactRender(createPortal(<InnerElement {...props} />, container), renderDom);
}
function destroy() {
reactUnmount(renderDom);
}
const currentConfig = {
...config,
open: true,
onCancel: () => {
render({ open: false, afterClose: destroy });
},
onOk: async (params) => {
const r = typeof config.onOk === 'function' ? config.onOk(params) : undefined;
render({ open: false, afterClose: destroy });
return r;
},
};
render(currentConfig);
return {
destroy,
};
}
InnerElement.show = show;
return InnerElement;
}
Modal组件文件
以CreateOrderModal.jsx
为例
import { withShowModal } from '../hoc/withShowModal';
import { Form, Modal, Select, InputNumber, message } from 'antd';
import { useEffect, useState, useMemo } from 'react';
const requiredRule = [
{
required: true,
message: '字段不能为空',
},
];
function ModalApp(props) {
const { onSuccess, ...rest } = props;
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const handleOk = async () => {
console.log('点击了ok');
setLoading(true);
try {
const vals = await form.validateFields();
message.info('正在创建订单');
console.log('vals: ', vals);
const res = await xxx()
if (res.status) {
message.success('创建成功');
onSuccess?.();
}
} catch (e) {
console.log(e);
message.warning('创建失败');
} finally {
setLoading(false);
}
};
const [formData, setFormData] = useState({});
const handleValsChange = (changeVal, allVal) => {
setFormData(allVal);
};
return (
<Modal
width={600}
centered
destroyOnClose
maskClosable={false}
{...rest}
onOk={handleOk}
okText='确定'
cancelText='取消'
okButtonProps={{
loading: loading,
}}
>
<Form
onValuesChange={handleValsChange}
name='createOrderForm'
form={form}
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
style={{
maxWidth: 600,
}}
initialValues={{}}
autoComplete='off'
>
<Form.Item
label='交易方式'
name='tradeType'
rules={requiredRule}
>
<Select
className='w-full'
options={[]}
/>
</Form.Item>
</Form>
</Modal>
);
}
export default withShowModal(ModalApp);
主页面调用
import { useRef } from 'react';
import { Button } from 'antd';
const Operation = () => {
const handleOrderCreate = async () => {
const { default: CreateOrderModal } = await import('@/components/CreateOrderModal');
const { destroy } = CreateOrderModal.show({
title: '创建订单',
onSuccess: () => {
destroy();
},
// 其它想要传给Modal的property
});
};
return (
<div>
<Button onClick={handleOrderCreate}>创建订单</Button>
</div>
);
};
export default Operation;
至此全部搞定