diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx
index ab93acda74cd..2dacea0979e8 100644
--- a/src/components/Modal/BaseModal.tsx
+++ b/src/components/Modal/BaseModal.tsx
@@ -117,7 +117,6 @@ function BaseModal({
                 onModalHide();
             }
             onModalDidClose();
-            ComposerFocusManager.setReadyToFocus(uniqueModalId);
             ComposerFocusManager.refocusAfterModalFullyClosed(uniqueModalId, restoreFocusType);
         },
         [shouldSetModalVisibility, onModalHide, restoreFocusType, uniqueModalId],
@@ -176,6 +175,10 @@ function BaseModal({
         }
     };
 
+    const handleDismissModal = () => {
+        ComposerFocusManager.setReadyToFocus(uniqueModalId);
+    };
+
     // Checks if modal overlaps with topSafeArea. Used to offset tall bottom docked modals with keyboard.
     useEffect(() => {
         if (type !== CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED || !canUseTouchScreen || !isSmallScreenWidth) {
@@ -323,6 +326,7 @@ function BaseModal({
                             }
                             onModalWillHide?.();
                         }}
+                        onDismiss={handleDismissModal}
                         onSwipeComplete={onClose}
                         swipeDirection={swipeDirection}
                         shouldPreventScrollOnFocus={shouldPreventScrollOnFocus}
diff --git a/src/components/Modal/ReanimatedModal/index.tsx b/src/components/Modal/ReanimatedModal/index.tsx
index 5460fa84c9bc..cdefc9742cb8 100644
--- a/src/components/Modal/ReanimatedModal/index.tsx
+++ b/src/components/Modal/ReanimatedModal/index.tsx
@@ -34,6 +34,7 @@ function ReanimatedModal({
     onModalShow = noop,
     onModalWillHide = noop,
     onModalHide = noop,
+    onDismiss,
     onBackdropPress = noop,
     onBackButtonPress = noop,
     style,
@@ -149,8 +150,16 @@ function ReanimatedModal({
             // eslint-disable-next-line @typescript-eslint/no-deprecated
             InteractionManager.clearInteractionHandle(handleRef.current);
         }
-        onModalHide();
-    }, [onModalHide]);
+
+        // On the web platform, the Modal's onDismiss callback may not be triggered if the dismiss process is interrupted by other actions such as navigation.
+        // Specifically on Android, the Modal's onDismiss callback does not work reliably. There's a reported issue at:
+        // https://stackoverflow.com/questions/58937956/react-native-modal-ondismiss-not-invoked
+        // Therefore, we manually call onDismiss and onModalHide here.
+        if (getPlatform() !== CONST.PLATFORM.IOS) {
+            onDismiss?.();
+            onModalHide();
+        }
+    }, [onDismiss, onModalHide]);
 
     const containerView = (
         <Container
@@ -207,6 +216,13 @@ function ReanimatedModal({
                 onRequestClose={onBackButtonPressHandler}
                 statusBarTranslucent={statusBarTranslucent}
                 testID={testID}
+                onDismiss={() => {
+                    if (getPlatform() !== CONST.PLATFORM.IOS) {
+                        return;
+                    }
+                    onDismiss?.();
+                    onModalHide();
+                }}
                 // eslint-disable-next-line react/jsx-props-no-spreading
                 {...props}
             >
diff --git a/src/components/Modal/ReanimatedModal/types.ts b/src/components/Modal/ReanimatedModal/types.ts
index 05ea66b0269d..f6ef33396da3 100644
--- a/src/components/Modal/ReanimatedModal/types.ts
+++ b/src/components/Modal/ReanimatedModal/types.ts
@@ -38,6 +38,9 @@ type ReanimatedModalProps = ViewProps &
         /** Style applied to the modal container */
         style?: StyleProp<ViewStyle>;
 
+        /** Callback when the modal is dismissed */
+        onDismiss?: () => void;
+
         /** Callback when the modal is shown */
         onShow?: () => void;
 
diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts
index ff57a8b3e043..1588b38ccf22 100644
--- a/src/hooks/useAutoFocusInput.ts
+++ b/src/hooks/useAutoFocusInput.ts
@@ -65,26 +65,13 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu
     // Trigger focus when Side Panel transition ends
     const {isSidePanelTransitionEnded, shouldHideSidePanel} = useSidePanel();
     const prevShouldHideSidePanel = usePrevious(shouldHideSidePanel);
-    const [wasSidePanelClosed, setWasSidePanelClosed] = useState(false);
-
     useEffect(() => {
-        // Track when side panel transitions from visible to hidden
-        if (!(shouldHideSidePanel && !prevShouldHideSidePanel)) {
+        if (!shouldHideSidePanel || prevShouldHideSidePanel) {
             return;
         }
-        setWasSidePanelClosed(true);
-    }, [shouldHideSidePanel, prevShouldHideSidePanel]);
 
-    useEffect(() => {
-        // Trigger focus when:
-        // 1. Side panel was just closed
-        // 2. Transition has fully completed
-        if (!wasSidePanelClosed || !isSidePanelTransitionEnded) {
-            return;
-        }
-        setWasSidePanelClosed(true);
         Promise.all([ComposerFocusManager.isReadyToFocus(), isWindowReadyToFocus()]).then(() => setIsScreenTransitionEnded(isSidePanelTransitionEnded));
-    }, [isSidePanelTransitionEnded, wasSidePanelClosed]);
+    }, [isSidePanelTransitionEnded, shouldHideSidePanel, prevShouldHideSidePanel]);
 
     const inputCallbackRef = (ref: TextInput | null) => {
         inputRef.current = ref;
