diff --git a/src/dialog/Dialog.tsx b/src/dialog/Dialog.tsx index 52841296a..86aee3479 100644 --- a/src/dialog/Dialog.tsx +++ b/src/dialog/Dialog.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef, useEffect, useMemo } from 'react'; +import React, { forwardRef, useEffect, useMemo, useRef } from 'react'; import isString from 'lodash/isString'; import { CloseIcon, InfoCircleFilledIcon, CheckCircleFilledIcon } from 'tdesign-icons-react'; import { useLocaleReceiver } from '../locale/LocalReceiver'; @@ -19,6 +19,7 @@ export interface DialogProps extends TdDialogProps, StyledProps { const Dialog = forwardRef((props: DialogProps, ref: React.Ref) => { const { classPrefix } = useConfig(); + const dialogDom = useRef(); const [state, setState] = useSetState({ width: 520, visible: false, @@ -75,7 +76,9 @@ const Dialog = forwardRef((props: DialogProps, ref: React.Ref) = hide() { setState({ visible: false }); }, - destroy: noop, + destroy() { + setState({ visible: false, destroyOnClose: true }); + }, update(newOptions) { setState((prevState) => ({ ...prevState, @@ -161,6 +164,7 @@ const Dialog = forwardRef((props: DialogProps, ref: React.Ref) = classPrefix={classPrefix} onClose={onClose} footer={footer === undefined ? defaultFooter() : footer} + ref={dialogDom} /> ); }); diff --git a/src/dialog/RenderDialog.tsx b/src/dialog/RenderDialog.tsx index fc179d775..105a61fa1 100644 --- a/src/dialog/RenderDialog.tsx +++ b/src/dialog/RenderDialog.tsx @@ -1,4 +1,4 @@ -import React, { useRef, CSSProperties, useEffect } from 'react'; +import React, { useRef, CSSProperties, useEffect, forwardRef, useImperativeHandle } from 'react'; import { CSSTransition } from 'react-transition-group'; import classnames from 'classnames'; import Portal from '../common/Portal'; @@ -30,7 +30,7 @@ const getClickPosition = (e: MouseEvent) => { if (typeof window !== 'undefined' && window.document && window.document.documentElement) { document.documentElement.addEventListener('click', getClickPosition, true); } -const RenderDialog: React.FC = (props) => { +const RenderDialog = forwardRef((props: RenderDialogProps, ref: React.Ref) => { const { prefixCls, attach, @@ -47,17 +47,19 @@ const RenderDialog: React.FC = (props) => { closeBtn, closeOnEscKeydown = true, closeOnOverlayClick = true, + destroyOnClose = false, } = props; const wrap = useRef(); const dialog = useRef(); const maskRef = useRef(); + const domRef = useRef(); const bodyOverflow = useRef(); const bodyCssTextRef = useRef(); const isModal = mode === 'modal'; const canDraggable = props.draggable && mode === 'modeless'; const dialogOpenClass = `${prefixCls}__open`; useDialogEsc(visible, wrap); - + useImperativeHandle(ref, () => domRef.current); useLayoutEffect(() => { bodyOverflow.current = document.body.style.overflow; bodyCssTextRef.current = document.body.style.cssText; @@ -119,6 +121,9 @@ const RenderDialog: React.FC = (props) => { style.left = '50%'; style.top = '50%'; } + if (destroyOnClose) { + domRef.current?.parentNode?.removeChild(domRef.current); + } onClosed && onClosed(); }; @@ -232,7 +237,7 @@ const RenderDialog: React.FC = (props) => { in={props.visible} appear mountOnEnter - unmountOnExit={props.destroyOnClose} + unmountOnExit={destroyOnClose} timeout={transitionTime} classNames={`${prefixCls}-zoom`} onEntered={props.onOpened} @@ -293,8 +298,13 @@ const RenderDialog: React.FC = (props) => { if (visible || wrap.current) { if (!attach) { dom = dialog; + domRef.current = dom; } else { - dom = {dialog}; + dom = ( + + {dialog} + + ); } } @@ -302,6 +312,6 @@ const RenderDialog: React.FC = (props) => { }; return render(); -}; +}); export default RenderDialog; diff --git a/src/dialog/plugin.tsx b/src/dialog/plugin.tsx index f23f954e9..190da3333 100644 --- a/src/dialog/plugin.tsx +++ b/src/dialog/plugin.tsx @@ -14,6 +14,7 @@ const createDialog: DialogPlugin = (props: DialogOptions): DialogInstance => { const dialogRef = React.createRef(); const options = { ...props }; const div = document.createElement('div'); + ReactDOM.render( , div, @@ -30,16 +31,19 @@ const createDialog: DialogPlugin = (props: DialogOptions): DialogInstance => { const dialogNode: DialogInstance = { show: () => { + container.appendChild(div); dialogRef.current?.show(); }, hide: () => { + div?.parentNode?.removeChild(div); dialogRef.current?.hide(); }, update: (updateOptions: DialogOptions) => { dialogRef.current?.update(updateOptions); }, destroy: () => { - container.contains(div) && container.removeChild(div); + dialogRef.current?.destroy(); + div?.parentNode?.removeChild(div); }, }; return dialogNode;