diff --git a/packages/experience/src/containers/SocialLinkAccount/use-social-link-related-user.ts b/packages/experience/src/containers/SocialLinkAccount/use-social-link-related-user.ts index 694772f32..dd035d493 100644 --- a/packages/experience/src/containers/SocialLinkAccount/use-social-link-related-user.ts +++ b/packages/experience/src/containers/SocialLinkAccount/use-social-link-related-user.ts @@ -24,7 +24,7 @@ const useBindSocialRelatedUser = () => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncBindSocialRelatedUser, handleError, preSignInErrorHandler, redirectTo] diff --git a/packages/experience/src/containers/VerificationCode/use-continue-flow-code-verification.ts b/packages/experience/src/containers/VerificationCode/use-continue-flow-code-verification.ts index e500de483..946d42cfa 100644 --- a/packages/experience/src/containers/VerificationCode/use-continue-flow-code-verification.ts +++ b/packages/experience/src/containers/VerificationCode/use-continue-flow-code-verification.ts @@ -78,7 +78,7 @@ const useContinueFlowCodeVerification = ( } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [ diff --git a/packages/experience/src/containers/VerificationCode/use-register-flow-code-verification.ts b/packages/experience/src/containers/VerificationCode/use-register-flow-code-verification.ts index 0dec679a8..5df3843d8 100644 --- a/packages/experience/src/containers/VerificationCode/use-register-flow-code-verification.ts +++ b/packages/experience/src/containers/VerificationCode/use-register-flow-code-verification.ts @@ -69,7 +69,7 @@ const useRegisterFlowCodeVerification = ( } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, onCancel: () => { @@ -118,7 +118,7 @@ const useRegisterFlowCodeVerification = ( } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [errorCallback, errorHandlers, handleError, redirectTo, verifyVerificationCode] diff --git a/packages/experience/src/containers/VerificationCode/use-sign-in-flow-code-verification.ts b/packages/experience/src/containers/VerificationCode/use-sign-in-flow-code-verification.ts index 16a6e0f7f..68f9987cf 100644 --- a/packages/experience/src/containers/VerificationCode/use-sign-in-flow-code-verification.ts +++ b/packages/experience/src/containers/VerificationCode/use-sign-in-flow-code-verification.ts @@ -72,7 +72,7 @@ const useSignInFlowCodeVerification = ( } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, onCancel: () => { @@ -119,7 +119,7 @@ const useSignInFlowCodeVerification = ( } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncSignInWithVerificationCodeIdentifier, errorHandlers, handleError, redirectTo] diff --git a/packages/experience/src/hooks/use-global-redirect-to.ts b/packages/experience/src/hooks/use-global-redirect-to.ts index b6c83148b..168d052d7 100644 --- a/packages/experience/src/hooks/use-global-redirect-to.ts +++ b/packages/experience/src/hooks/use-global-redirect-to.ts @@ -1,27 +1,47 @@ +import { noop } from '@react-spring/shared'; import { useCallback, useContext } from 'react'; import PageContext from '@/Providers/PageContextProvider/PageContext'; import UserInteractionContext from '@/Providers/UserInteractionContextProvider/UserInteractionContext'; /** - * This hook provides a function that process the app redirection after user successfully signs in. - * Use window.location.replace to handle the redirection. - * Set the global loading state to true before redirecting. - * This is to prevent the user from interacting with the app while the redirection is in progress. + * Hook for global redirection after successful login. + * + * This hook provides an async function that represents the final step in the login process. + * It sets a global loading state, clears the interaction context, and then redirects the user. + * + * The returned async function will never resolve, as the page will be redirected before + * the Promise can settle. This behavior is intentional and serves to maintain the loading + * state on the interaction element (e.g., a button) that triggered the successful login. */ function useGlobalRedirectTo() { const { setLoading } = useContext(PageContext); const { clearInteractionContextSessionStorage } = useContext(UserInteractionContext); const redirectTo = useCallback( - (url: string | URL) => { + async (url: string | URL): Promise => { + /** + * Set global loading state to true + * This prevents further user interaction during the redirect process + */ setLoading(true); /** * Clear all identifier input values from the storage once the interaction is submitted. * The Identifier cache should be session-isolated, so it should be cleared after the interaction is completed. */ clearInteractionContextSessionStorage(); + /** + * Perform the actual redirect + * This is a synchronous operation and will immediately unload the current page + */ window.location.replace(url); + + /** + * Return a Promise that never resolves + * This ensures that any async function awaiting this redirect will never continue + * Thus maintaining the loading state on the UI until the new page is loaded + */ + return new Promise(noop); }, [clearInteractionContextSessionStorage, setLoading] ); diff --git a/packages/experience/src/hooks/use-password-sign-in.ts b/packages/experience/src/hooks/use-password-sign-in.ts index 459cfa15c..23cce8bcb 100644 --- a/packages/experience/src/hooks/use-password-sign-in.ts +++ b/packages/experience/src/hooks/use-password-sign-in.ts @@ -53,7 +53,7 @@ const usePasswordSignIn = () => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncSignIn, checkSingleSignOn, errorHandlers, handleError, redirectTo] diff --git a/packages/experience/src/hooks/use-send-mfa-payload.ts b/packages/experience/src/hooks/use-send-mfa-payload.ts index 9d72a9471..e407bb323 100644 --- a/packages/experience/src/hooks/use-send-mfa-payload.ts +++ b/packages/experience/src/hooks/use-send-mfa-payload.ts @@ -50,7 +50,7 @@ const useSendMfaPayload = () => { } if (result) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncSendMfaPayload, handleError, preSignInErrorHandler, redirectTo] diff --git a/packages/experience/src/hooks/use-skip-mfa.ts b/packages/experience/src/hooks/use-skip-mfa.ts index 233bfed1d..af480682b 100644 --- a/packages/experience/src/hooks/use-skip-mfa.ts +++ b/packages/experience/src/hooks/use-skip-mfa.ts @@ -22,7 +22,7 @@ const useSkipMfa = () => { } if (result) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncSkipMfa, handleError, preSignInErrorHandler, redirectTo]); }; diff --git a/packages/experience/src/hooks/use-social-link-account.ts b/packages/experience/src/hooks/use-social-link-account.ts index 16c38e7f3..4e75ffbf1 100644 --- a/packages/experience/src/hooks/use-social-link-account.ts +++ b/packages/experience/src/hooks/use-social-link-account.ts @@ -22,7 +22,7 @@ const useLinkSocial = () => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncLinkWithSocial, handleError, redirectTo] diff --git a/packages/experience/src/hooks/use-social-register.ts b/packages/experience/src/hooks/use-social-register.ts index 8d128f538..601780077 100644 --- a/packages/experience/src/hooks/use-social-register.ts +++ b/packages/experience/src/hooks/use-social-register.ts @@ -25,7 +25,7 @@ const useSocialRegister = (connectorId?: string, replace?: boolean) => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncRegisterWithSocial, handleError, preSignInErrorHandler, redirectTo] diff --git a/packages/experience/src/pages/Consent/index.tsx b/packages/experience/src/pages/Consent/index.tsx index 8052e11d8..3c594989a 100644 --- a/packages/experience/src/pages/Consent/index.tsx +++ b/packages/experience/src/pages/Consent/index.tsx @@ -43,7 +43,7 @@ const Consent = () => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncConsent, handleError, redirectTo, selectedOrganization?.id]); diff --git a/packages/experience/src/pages/Continue/SetPassword/index.tsx b/packages/experience/src/pages/Continue/SetPassword/index.tsx index 64530f584..da72cd53d 100644 --- a/packages/experience/src/pages/Continue/SetPassword/index.tsx +++ b/packages/experience/src/pages/Continue/SetPassword/index.tsx @@ -34,9 +34,9 @@ const SetPassword = () => { [navigate, preSignInErrorHandler, show] ); const successHandler: SuccessHandler = useCallback( - (result) => { + async (result) => { if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [redirectTo] diff --git a/packages/experience/src/pages/Continue/SetUsername/use-set-username.ts b/packages/experience/src/pages/Continue/SetUsername/use-set-username.ts index 4f51873f9..343ac0de6 100644 --- a/packages/experience/src/pages/Continue/SetUsername/use-set-username.ts +++ b/packages/experience/src/pages/Continue/SetUsername/use-set-username.ts @@ -41,7 +41,7 @@ const useSetUsername = () => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [asyncAddProfile, errorHandlers, handleError, redirectTo] diff --git a/packages/experience/src/pages/RegisterPassword/index.tsx b/packages/experience/src/pages/RegisterPassword/index.tsx index b276b2c4e..4c0c722aa 100644 --- a/packages/experience/src/pages/RegisterPassword/index.tsx +++ b/packages/experience/src/pages/RegisterPassword/index.tsx @@ -40,9 +40,9 @@ const RegisterPassword = () => { ); const successHandler: SuccessHandler = useCallback( - (result) => { + async (result) => { if (result && 'redirectTo' in result) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [redirectTo] diff --git a/packages/experience/src/pages/SocialSignInWebCallback/use-single-sign-on-listener.ts b/packages/experience/src/pages/SocialSignInWebCallback/use-single-sign-on-listener.ts index 678b1872d..bfc0b8da1 100644 --- a/packages/experience/src/pages/SocialSignInWebCallback/use-single-sign-on-listener.ts +++ b/packages/experience/src/pages/SocialSignInWebCallback/use-single-sign-on-listener.ts @@ -41,7 +41,7 @@ const useSingleSignOnRegister = () => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [agreeToTermsPolicy, handleError, navigate, redirectTo, request, termsValidation] @@ -104,7 +104,7 @@ const useSingleSignOnListener = (connectorId: string) => { } if (result?.redirectTo) { - redirectTo(result.redirectTo); + await redirectTo(result.redirectTo); } }, [