@@ -3,6 +3,7 @@ import {useEffect, useEffectEvent, useRef} from 'react';
33import useOnyx from '@hooks/useOnyx' ;
44import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute' ;
55import Navigation from '@libs/Navigation/Navigation' ;
6+ import { clearPaymentCard3dsVerification } from '@userActions/PaymentMethods' ;
67import ONYXKEYS from '@src/ONYXKEYS' ;
78import { DYNAMIC_ROUTES } from '@src/ROUTES' ;
89
@@ -20,6 +21,12 @@ import {DYNAMIC_ROUTES} from '@src/ROUTES';
2021 * its own `route.name` to the producing action, which records it in `verify3dsSubscriptionSource`. A
2122 * mounted hook only reacts to a link when its own focused screen matches that source, so a link can
2223 * never be consumed by an unrelated screen the user has since navigated to.
24+ *
25+ * If the focused screen is NOT the link's owner (the user left the flow that started the request
26+ * before the link arrived), the link is orphaned — it can never be consumed. The focused hook clears
27+ * it so a later identical link from a fresh attempt still registers as a change and can reopen the
28+ * challenge. Only the focused screen clears, so an unfocused background instance can't wipe a link the
29+ * focused owner is about to consume.
2330 */
2431function useNavigateToCardAuthenticationOnLink ( ) {
2532 const [ authenticationLink ] = useOnyx ( ONYXKEYS . VERIFY_3DS_SUBSCRIPTION ) ;
@@ -33,7 +40,16 @@ function useNavigateToCardAuthenticationOnLink() {
3340 firstRenderRef . current = false ;
3441 return ;
3542 }
36- if ( ! isFocused || route . name !== source || ! authenticationLink ) {
43+ // Only the focused screen acts on a link change. Unfocused mounted instances bail so they can
44+ // neither navigate nor clear a link the focused screen may still need to consume.
45+ if ( ! isFocused || ! authenticationLink ) {
46+ return ;
47+ }
48+ if ( route . name !== source ) {
49+ // Focused, but this link belongs to a different screen: the user left the flow that started it
50+ // before the link arrived. Drop the orphaned link so a later identical link from a fresh attempt
51+ // still registers as a change and can reopen the challenge (mirrors the close-time clear).
52+ clearPaymentCard3dsVerification ( ) ;
3753 return ;
3854 }
3955 Navigation . navigate ( createDynamicRoute ( DYNAMIC_ROUTES . CARD_AUTHENTICATION . path ) ) ;
0 commit comments