From a7f7864d1159ced666602fb99c7950e4bd2059fe Mon Sep 17 00:00:00 2001 From: Eskalifer1 Date: Thu, 9 Oct 2025 14:42:29 +0300 Subject: [PATCH 1/3] follow-up:69781: added stable function call is eventListener --- src/components/Modal/index.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 6c6e3f9e0d2c..5711a36b08ca 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useRef, useState} from 'react'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import StatusBar from '@libs/StatusBar'; @@ -38,17 +38,21 @@ function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, [rest.onClose]); + const handlePopState = useCallback(() => { + handlePopStateRef.current(); + }, []); + const showModal = () => { if (shouldHandleNavigationBack) { window.history.pushState({shouldGoBack: true}, '', null); - window.addEventListener('popstate', handlePopStateRef.current); + window.addEventListener('popstate', handlePopState); } onModalShow?.(); }; useEffect( () => () => { - window.removeEventListener('popstate', handlePopStateRef.current); + window.removeEventListener('popstate', handlePopState); }, [], ); From 765080f8f9664526a683a55ab3a197f4f7fe117b Mon Sep 17 00:00:00 2001 From: Eskalifer1 Date: Fri, 10 Oct 2025 14:41:39 +0300 Subject: [PATCH 2/3] chore: C+ comments --- src/components/Modal/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 5711a36b08ca..843790a625b3 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -38,6 +38,7 @@ function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, [rest.onClose]); + // We need to pass stable version of the function to properly work in eventListener const handlePopState = useCallback(() => { handlePopStateRef.current(); }, []); @@ -54,7 +55,7 @@ function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = ( () => () => { window.removeEventListener('popstate', handlePopState); }, - [], + [handlePopState], ); const onModalWillShow = () => { From 17b24dab381969b132c208e629d94e2bd3b5556c Mon Sep 17 00:00:00 2001 From: Eskalifer1 Date: Wed, 15 Oct 2025 00:51:32 +0300 Subject: [PATCH 3/3] chore: added comment --- src/components/Modal/index.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 843790a625b3..c9a7e47fbe41 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -38,7 +38,12 @@ function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, [rest.onClose]); - // We need to pass stable version of the function to properly work in eventListener + // We use a stable callback here to avoid issues with stale closures in event listeners. + // If we directly passed `handlePopStateRef.current` to addEventListener, the listener would + // capture the value of `onClose` at the time it was registered and would not update when + // `onClose` changes. By wrapping it in a stable useCallback and referencing + // handlePopStateRef.current inside, we ensure that the listener always calls the latest + // version of `onClose` without needing to reattach the event listener. const handlePopState = useCallback(() => { handlePopStateRef.current(); }, []);