From 3f8f05368c5b4fb184ac8094506459c57325b95d Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 28 Sep 2025 11:10:39 +0300 Subject: [PATCH] fix(modal): event leak for onHidden --- apps/client/src/widgets/react/Modal.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/client/src/widgets/react/Modal.tsx b/apps/client/src/widgets/react/Modal.tsx index f13257a5d..37a0d96c0 100644 --- a/apps/client/src/widgets/react/Modal.tsx +++ b/apps/client/src/widgets/react/Modal.tsx @@ -36,9 +36,9 @@ interface ModalProps { onSubmit?: () => void; /** Called when the modal is shown. */ onShown?: () => void; - /** + /** * Called when the modal is hidden, either via close button, backdrop click or submit. - * + * * Here it's generally a good idea to set `show` to false to reflect the actual state of the modal. */ onHidden: () => void; @@ -71,23 +71,25 @@ export default function Modal({ children, className, size, title, header, footer useEffect(() => { const modalElement = modalRef.current; - if (!modalElement) { - return; - } + if (!modalElement) return; + if (onShown) { modalElement.addEventListener("shown.bs.modal", onShown); } - modalElement.addEventListener("hidden.bs.modal", () => { + + function onModalHidden() { onHidden(); if (elementToFocus.current && "focus" in elementToFocus.current) { (elementToFocus.current as HTMLElement).focus(); } - }); + } + + modalElement.addEventListener("hidden.bs.modal", onModalHidden); return () => { if (onShown) { modalElement.removeEventListener("shown.bs.modal", onShown); } - modalElement.removeEventListener("hidden.bs.modal", onHidden); + modalElement.removeEventListener("hidden.bs.modal", onModalHidden); }; }, [ onShown, onHidden ]); @@ -180,4 +182,4 @@ const ModalInner = memo(({ children, footer, footerAlignment, bodyStyle, footerS )} ); -}); \ No newline at end of file +});