Skip to content

Commit 1fe87ac

Browse files
authored
fix(clerk-js): prevent infinite spinner on factor-two without active 2fa session (#7787)
1 parent 8cb461d commit 1fe87ac

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
Fix infinite loading spinner when navigating to factor-two sign-in route without an active 2FA session

packages/clerk-js/src/ui/components/SignIn/SignInFactorTwo.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useClerk } from '@clerk/shared/react';
12
import type { SignInFactor } from '@clerk/shared/types';
23
import React from 'react';
34

@@ -6,6 +7,7 @@ import { LoadingCard } from '@/ui/elements/LoadingCard';
67

78
import { withRedirectToAfterSignIn, withRedirectToSignInTask } from '../../common';
89
import { useCoreSignIn } from '../../contexts';
10+
import { useRouter } from '../../router';
911
import { SignInFactorTwoAlternativeMethods } from './SignInFactorTwoAlternativeMethods';
1012
import { SignInFactorTwoBackupCodeCard } from './SignInFactorTwoBackupCodeCard';
1113
import { SignInFactorTwoEmailCodeCard } from './SignInFactorTwoEmailCodeCard';
@@ -26,7 +28,9 @@ const factorKey = (factor: SignInFactor | null | undefined) => {
2628
};
2729

2830
function SignInFactorTwoInternal(): JSX.Element {
31+
const { __internal_setActiveInProgress } = useClerk();
2932
const signIn = useCoreSignIn();
33+
const router = useRouter();
3034
const availableFactors = signIn.supportedSecondFactors;
3135

3236
const lastPreparedFactorKeyRef = React.useRef('');
@@ -45,6 +49,19 @@ function SignInFactorTwoInternal(): JSX.Element {
4549
toggleAllStrategies();
4650
};
4751

52+
React.useEffect(() => {
53+
if (__internal_setActiveInProgress) {
54+
return;
55+
}
56+
57+
// If the sign-in was reset or doesn't exist, redirect back to the start.
58+
// Don't redirect for 'complete' status - setActive will handle navigation.
59+
if (signIn.status === null || signIn.status === 'needs_identifier' || signIn.status === 'needs_first_factor') {
60+
void router.navigate('../');
61+
}
62+
// eslint-disable-next-line react-hooks/exhaustive-deps -- Match SignInFactorOne pattern: only run on mount and when setActiveInProgress changes
63+
}, [__internal_setActiveInProgress]);
64+
4865
if (!currentFactor) {
4966
return <LoadingCard />;
5067
}

0 commit comments

Comments
 (0)