Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/friendly-dots-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/elements": patch
---

Fix Sign In & Sign Up root fallbacks not rendering as expected
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ export default function SignUpPage() {
<Clerk.Icon />
Sign In with Google
</Clerk.Connection>

<Clerk.Connection

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used, per configuration

name='metamask'
className='flex items-center justify-center gap-4 rounded bg-white px-4 py-3 text-sm text-[#161616] shadow-sm ring-1 ring-black/[0.06] transition-all hover:bg-opacity-80'
>
<Clerk.Icon />
Sign In with Metamask
</Clerk.Connection>
</div>

<Hr />
Expand Down Expand Up @@ -142,14 +134,6 @@ export default function SignUpPage() {
<Clerk.Icon />
Sign In with Google
</Clerk.Connection>

<Clerk.Connection
name='metamask'
className='flex items-center justify-center gap-4 rounded bg-white px-4 py-3 text-sm text-[#161616] shadow-sm ring-1 ring-black/[0.06] transition-all hover:bg-opacity-80'
>
<Clerk.Icon />
Sign In with Metamask
</Clerk.Connection>
</div>

<Hr />
Expand Down
3 changes: 2 additions & 1 deletion packages/elements/src/react/common/form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ const useInput = ({
const FORM_NAME = 'ClerkElementsForm';

type FormElement = React.ElementRef<typeof RadixForm>;
type FormProps = SetRequired<RadixFormProps, 'children'> & {
type FormProps = Omit<RadixFormProps, 'children'> & {
children: React.ReactNode;
flowActor?: BaseActorRef<{ type: 'SUBMIT' }>;
};

Expand Down
39 changes: 23 additions & 16 deletions packages/elements/src/react/sign-in/root.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ClerkLoaded, ClerkLoading, useClerk } from '@clerk/clerk-react';
import { useClerk } from '@clerk/clerk-react';
import { eventComponentMounted } from '@clerk/shared/telemetry';
import { useSelector } from '@xstate/react';
import React, { useEffect } from 'react';
import { createActor } from 'xstate';

Expand All @@ -17,15 +18,21 @@ import { usePathnameWithoutCatchAll } from '../utils/path-inference/next';
type SignInFlowProviderProps = {
children: React.ReactNode;
exampleMode?: boolean;
/**
* Fallback markup to render while Clerk is loading
*/
fallback?: React.ReactNode;
isRootPath: boolean;
};

const actor = createActor(SignInRouterMachine, { inspect });
actor.start();

function SignInFlowProvider({ children, exampleMode }: SignInFlowProviderProps) {
function SignInFlowProvider({ children, exampleMode, fallback, isRootPath }: SignInFlowProviderProps) {
const clerk = useClerk();
const router = useClerkRouter();
const formRef = useFormStore();
const isReady = useSelector(actor, state => state.value !== 'Idle');

useEffect(() => {
if (!clerk || !router) {
Expand Down Expand Up @@ -57,16 +64,17 @@ function SignInFlowProvider({ children, exampleMode }: SignInFlowProviderProps)
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [clerk, exampleMode, formRef?.id, !!router]);
}, [clerk, exampleMode, formRef?.id, !!router, clerk.loaded]);

return <SignInRouterCtx.Provider actorRef={actor}>{children}</SignInRouterCtx.Provider>;
return (
<SignInRouterCtx.Provider actorRef={actor}>
{isRootPath && !isReady && fallback ? <Form>{fallback}</Form> : null}
{clerk.loaded && isReady ? children : null}
</SignInRouterCtx.Provider>
);
}

export type SignInRootProps = SignInFlowProviderProps & {
/**
* Fallback markup to render while Clerk is loading
*/
fallback?: React.ReactNode;
export type SignInRootProps = Omit<SignInFlowProviderProps, 'isRootPath'> & {
/**
* The base path for your sign-in route.
* Will be automatically inferred in Next.js.
Expand Down Expand Up @@ -125,13 +133,12 @@ export function SignInRoot({
router={router}
>
<FormStoreProvider>
<SignInFlowProvider exampleMode={exampleMode}>
{isRootPath ? (
<ClerkLoading>
<Form>{fallback}</Form>
</ClerkLoading>
) : null}
<ClerkLoaded>{children}</ClerkLoaded>
<SignInFlowProvider
exampleMode={exampleMode}
fallback={fallback}
isRootPath={isRootPath}
>
{children}
</SignInFlowProvider>
</FormStoreProvider>
</Router>
Expand Down
37 changes: 21 additions & 16 deletions packages/elements/src/react/sign-up/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ClerkLoaded, ClerkLoading, useClerk } from '@clerk/clerk-react';
import { useClerk } from '@clerk/clerk-react';
import { eventComponentMounted } from '@clerk/shared/telemetry';
import { useSelector } from '@xstate/react';
import { useEffect } from 'react';
Expand All @@ -18,12 +18,17 @@ import { usePathnameWithoutCatchAll } from '../utils/path-inference/next';
type SignUpFlowProviderProps = {
children: React.ReactNode;
exampleMode?: boolean;
/**
* Fallback markup to render while Clerk is loading
*/
fallback?: React.ReactNode;
isRootPath: boolean;
};

const actor = createActor(SignUpRouterMachine, { inspect });
actor.start();

function SignUpFlowProvider({ children, exampleMode }: SignUpFlowProviderProps) {
function SignUpFlowProvider({ children, exampleMode, fallback, isRootPath }: SignUpFlowProviderProps) {
const clerk = useClerk();
const router = useClerkRouter();
const formRef = useFormStore();
Expand Down Expand Up @@ -58,16 +63,17 @@ function SignUpFlowProvider({ children, exampleMode }: SignUpFlowProviderProps)
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [clerk, exampleMode, formRef?.id, !!router]);
}, [clerk, exampleMode, formRef?.id, !!router, clerk.loaded]);

return isReady ? <SignUpRouterCtx.Provider actorRef={actor}>{children}</SignUpRouterCtx.Provider> : null;
return (
<SignUpRouterCtx.Provider actorRef={actor}>
{isRootPath && !isReady && fallback ? <Form>{fallback}</Form> : null}
{clerk.loaded && isReady ? children : null}
</SignUpRouterCtx.Provider>
);
}

export type SignUpRootProps = SignUpFlowProviderProps & {
/**
* Fallback markup to render while Clerk is loading
*/
fallback?: React.ReactNode;
export type SignUpRootProps = Omit<SignUpFlowProviderProps, 'isRootPath'> & {
/**
* The base path for your sign-up route.
* Will be automatically inferred in Next.js.
Expand Down Expand Up @@ -126,13 +132,12 @@ export function SignUpRoot({
router={router}
>
<FormStoreProvider>
<SignUpFlowProvider exampleMode={exampleMode}>
{isRootPath ? (
<ClerkLoading>
<Form>{fallback}</Form>
</ClerkLoading>
) : null}
<ClerkLoaded>{children}</ClerkLoaded>
<SignUpFlowProvider
exampleMode={exampleMode}
fallback={fallback}
isRootPath={isRootPath}
>
{children}
</SignUpFlowProvider>
</FormStoreProvider>
</Router>
Expand Down