|
- /*
- * @Author: 赵伟
- * @Date: 2024-04-13 10:08:35
- * @Description:
- */
- import { ConfigProvider, type ModalProps } from 'antd';
- import { globalConfig } from 'antd/es/config-provider';
- import React, { useState } from 'react';
- import { createRoot } from 'react-dom/client';
-
- /**
- * 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 = <T extends ModalProps>(
- 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<typeof setTimeout>;
-
- function destroy() {
- 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<HTMLButtonElement, 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 = (
- <CustomModel {...props} onCancel={handleCancel} afterClose={handleAfterClose}></CustomModel>
- );
-
- root.render(
- <ConfigProvider prefixCls={rootPrefixCls} iconPrefixCls={iconPrefixCls} theme={theme}>
- {global.holderRender ? global.holderRender(dom) : dom}
- </ConfigProvider>,
- );
- });
- }
-
- function close() {
- render({ ...modalProps, open: false });
- }
-
- render({ ...modalProps, open: true });
-
- return {
- close,
- };
- };
-
- /**
- * Generates a custom hook for managing an Ant Design modal.
- *
- * @param modal - The function that renders the modal content.
- * @param key - The key for the modal.
- * @return The modal component, open function, and close function.
- */
- export const useAntdModal = <T extends ModalProps>(
- modal: (props: T) => React.ReactNode,
- key: React.Key,
- ) => {
- const [visible, setVisible] = useState(false);
- const [props, setProps] = useState<T>({} as T);
- const CustomModel = modal;
-
- const open = (props: T) => {
- setProps(props);
- setVisible(true);
- };
-
- const close = () => {
- setVisible(false);
- };
-
- return [<CustomModel key={key} open={visible} {...props} />, open, close] as const;
- };
|