/* * @Author: 赵伟 * @Date: 2024-04-13 10:08:35 * @Description: 以函数的方式打开 Modal */ import { ConfigProvider, type ModalProps } from 'antd'; import { globalConfig } from 'antd/es/config-provider'; import zhCN from 'antd/locale/zh_CN'; import React, { useState } from 'react'; import { createRoot } from 'react-dom/client'; const destroyFns: (() => void)[] = []; /** * Function to open an Ant Design modal. * * @param modal - The function that renders the modal content. * @param modalProps - The modal properties. * @return An object with a destroy method to close the modal. */ export const openAntdModal = >( modal: (props: T) => React.ReactNode, modalProps: T, ) => { const CustomModel = modal; const container = document.createDocumentFragment(); const root = createRoot(container); const { afterClose, onCancel } = modalProps; const global = globalConfig(); let timeoutId: ReturnType; function destroy() { const index = destroyFns.indexOf(close); if (index !== -1) { destroyFns.splice(index, 1); } root.unmount(); } function handleAfterClose() { afterClose?.(); // Warning: Attempted to synchronously unmount a root while React was already rendering. // React cannot finish unmounting the root until the current render has completed, which may lead to a race condition. setTimeout(() => { destroy(); }, 0); } function handleCancel(e: React.MouseEvent) { if (onCancel) { onCancel(e); } else { close(); } } function render(props: T) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { const rootPrefixCls = global.getPrefixCls(); const iconPrefixCls = global.getIconPrefixCls(); const theme = global.getTheme(); const dom = ( ); root.render( {global.holderRender ? global.holderRender(dom) : dom} , ); }); } function close() { render({ ...modalProps, open: false }); } render({ ...modalProps, open: true }); destroyFns.push(close); return { close, }; }; /** * Generates a custom hook for managing an Ant Design modal. * * @param modal - The function that renders the modal content. * @param defaultProps - The default modal properties. * @return The modal component, open function, and close function. */ export const useModal = ( modal: (props: T) => React.ReactNode, defaultProps?: T, ) => { const [visible, setVisible] = useState(false); const [props, setProps] = useState(defaultProps || ({} as T)); const CustomModel = modal; const open = (props: T) => { setProps((prev) => ({ ...prev, ...props, })); setVisible(true); }; const close = () => { setVisible(false); }; return [, open, close] as const; }; // 关闭没有手动关闭的 Modal export const closeAllModals = () => { let close = destroyFns.pop(); while (close) { close(); close = destroyFns.pop(); } };