mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(console): keep button loading before redirecting to sign-in success page (#6305)
This commit is contained in:
parent
5ee47af00c
commit
16c8d330f0
15 changed files with 44 additions and 24 deletions
|
@ -24,7 +24,7 @@ const useBindSocialRelatedUser = () => {
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[asyncBindSocialRelatedUser, handleError, preSignInErrorHandler, redirectTo]
|
||||
|
|
|
@ -78,7 +78,7 @@ const useContinueFlowCodeVerification = (
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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<never> => {
|
||||
/**
|
||||
* 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<never>(noop);
|
||||
},
|
||||
[clearInteractionContextSessionStorage, setLoading]
|
||||
);
|
||||
|
|
|
@ -53,7 +53,7 @@ const usePasswordSignIn = () => {
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[asyncSignIn, checkSingleSignOn, errorHandlers, handleError, redirectTo]
|
||||
|
|
|
@ -50,7 +50,7 @@ const useSendMfaPayload = () => {
|
|||
}
|
||||
|
||||
if (result) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[asyncSendMfaPayload, handleError, preSignInErrorHandler, redirectTo]
|
||||
|
|
|
@ -22,7 +22,7 @@ const useSkipMfa = () => {
|
|||
}
|
||||
|
||||
if (result) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
}, [asyncSkipMfa, handleError, preSignInErrorHandler, redirectTo]);
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ const useLinkSocial = () => {
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[asyncLinkWithSocial, handleError, redirectTo]
|
||||
|
|
|
@ -25,7 +25,7 @@ const useSocialRegister = (connectorId?: string, replace?: boolean) => {
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[asyncRegisterWithSocial, handleError, preSignInErrorHandler, redirectTo]
|
||||
|
|
|
@ -43,7 +43,7 @@ const Consent = () => {
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
}, [asyncConsent, handleError, redirectTo, selectedOrganization?.id]);
|
||||
|
||||
|
|
|
@ -34,9 +34,9 @@ const SetPassword = () => {
|
|||
[navigate, preSignInErrorHandler, show]
|
||||
);
|
||||
const successHandler: SuccessHandler<typeof addProfile> = useCallback(
|
||||
(result) => {
|
||||
async (result) => {
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[redirectTo]
|
||||
|
|
|
@ -41,7 +41,7 @@ const useSetUsername = () => {
|
|||
}
|
||||
|
||||
if (result?.redirectTo) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[asyncAddProfile, errorHandlers, handleError, redirectTo]
|
||||
|
|
|
@ -40,9 +40,9 @@ const RegisterPassword = () => {
|
|||
);
|
||||
|
||||
const successHandler: SuccessHandler<typeof setUserPassword> = useCallback(
|
||||
(result) => {
|
||||
async (result) => {
|
||||
if (result && 'redirectTo' in result) {
|
||||
redirectTo(result.redirectTo);
|
||||
await redirectTo(result.redirectTo);
|
||||
}
|
||||
},
|
||||
[redirectTo]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
},
|
||||
[
|
||||
|
|
Loading…
Reference in a new issue