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/itchy-mirrors-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/elements': patch
---

Fix forms unable to submit upon re-mounting
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import * as Clerk from '@clerk/elements/common';
import * as SignUp from '@clerk/elements/sign-up';
import Link from 'next/link';
import type { ComponentProps } from 'react';

import { H1, HR as Hr, P } from '@/components/design';
Expand Down Expand Up @@ -42,6 +43,16 @@ export default function SignUpPage() {
<div className='flex flex-col items-center justify-center gap-12'>
<H1>Sign Up</H1>

<p className='text-base text-zinc-400'>
Have an account?{' '}
<Link
href='/sign-in'
className='no-underline hover:underline'
>
Sign In
</Link>
</p>

<div className='flex flex-col items-stretch justify-center gap-2'>
<Clerk.Connection
name='github'
Expand Down Expand Up @@ -105,6 +116,16 @@ export default function SignUpPage() {
<div className='flex flex-col items-center justify-center gap-12'>
<H1>Sign Up</H1>

<p className='text-base text-zinc-400'>
Have an account?{' '}
<Link
href='/sign-in'
className='no-underline hover:underline'
>
Sign In
</Link>
</p>

<div className='flex flex-col items-stretch justify-center gap-2'>
<Clerk.Connection
name='github'
Expand Down
27 changes: 27 additions & 0 deletions packages/elements/src/internals/machines/sign-in/router.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@ export const SignInRouterMachine = setup({
params: { strategy: 'saml' },
}),
},
'FORM.ATTACH': {
description: 'Attach/re-attach the form to the router.',
actions: enqueueActions(({ enqueue, event }) => {
enqueue.assign({
formRef: event.formRef,
});

// Reset the current step, to reset the form reference.
enqueue.raise({ type: 'RESET.STEP' });
}),
},
'NAVIGATE.PREVIOUS': '.Hist',
'NAVIGATE.START': '.Start',
LOADING: {
Expand Down Expand Up @@ -292,6 +303,10 @@ export const SignInRouterMachine = setup({
},
},
on: {
'RESET.STEP': {
target: 'Start',
reenter: true,
},
NEXT: [
{
guard: 'isComplete',
Expand Down Expand Up @@ -329,6 +344,10 @@ export const SignInRouterMachine = setup({
},
},
on: {
'RESET.STEP': {
target: 'FirstFactor',
reenter: true,
},
NEXT: [
{
guard: 'isComplete',
Expand Down Expand Up @@ -399,6 +418,10 @@ export const SignInRouterMachine = setup({
},
},
on: {
'RESET.STEP': {
target: 'SecondFactor',
reenter: true,
},
NEXT: [
{
guard: 'isComplete',
Expand Down Expand Up @@ -426,6 +449,10 @@ export const SignInRouterMachine = setup({
},
},
on: {
'RESET.STEP': {
target: 'ResetPassword',
reenter: true,
},
NEXT: [
{
guard: 'isComplete',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import type { TFormMachine } from '~/internals/machines/form';
import type {
BaseRouterContext,
BaseRouterErrorEvent,
BaseRouterFormAttachEvent,
BaseRouterInput,
BaseRouterLoadingEvent,
BaseRouterNextEvent,
BaseRouterPrevEvent,
BaseRouterRedirectEvent,
BaseRouterResetEvent,
BaseRouterResetStepEvent,
BaseRouterSetClerkEvent,
BaseRouterStartEvent,
BaseRouterTransferEvent,
Expand Down Expand Up @@ -47,6 +49,7 @@ export type SignInRouterSystemId = keyof typeof SignInRouterSystemId;

// ---------------------------------- Events ---------------------------------- //

export type SignInRouterFormAttachEvent = BaseRouterFormAttachEvent;
export type SignInRouterNextEvent = BaseRouterNextEvent<SignInResource>;
export type SignInRouterStartEvent = BaseRouterStartEvent;
export type SignInRouterPrevEvent = BaseRouterPrevEvent;
Expand All @@ -56,6 +59,7 @@ export type SignInRouterErrorEvent = BaseRouterErrorEvent;
export type SignInRouterTransferEvent = BaseRouterTransferEvent;
export type SignInRouterRedirectEvent = BaseRouterRedirectEvent;
export type SignInRouterResetEvent = BaseRouterResetEvent;
export type SignInRouterResetStepEvent = BaseRouterResetStepEvent;
export type SignInRouterLoadingEvent = BaseRouterLoadingEvent<'start' | 'verifications' | 'reset-password'>;
export type SignInRouterSetClerkEvent = BaseRouterSetClerkEvent;
export type SignInRouterSubmitEvent = { type: 'SUBMIT' };
Expand All @@ -73,13 +77,15 @@ export type SignInRouterNavigationEvents =
| SignInRouterPrevEvent;

export type SignInRouterEvents =
| SignInRouterFormAttachEvent
| SignInRouterInitEvent
| SignInRouterNextEvent
| SignInRouterNavigationEvents
| SignInRouterErrorEvent
| SignInRouterTransferEvent
| SignInRouterRedirectEvent
| SignInRouterResetEvent
| SignInRouterResetStepEvent
| SignInVerificationFactorUpdateEvent
| SignInRouterLoadingEvent
| SignInRouterSetClerkEvent
Expand Down
23 changes: 23 additions & 0 deletions packages/elements/src/internals/machines/sign-up/router.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ export const SignUpRouterMachine = setup({
params: { strategy: 'saml' },
}),
},
'FORM.ATTACH': {
description: 'Attach/re-attach the form to the router.',
actions: enqueueActions(({ enqueue, event }) => {
enqueue.assign({
formRef: event.formRef,
});

// Reset the current step, to reset the form reference.
enqueue.raise({ type: 'RESET.STEP' });
}),
},
'NAVIGATE.PREVIOUS': '.Hist',
'NAVIGATE.START': '.Start',
LOADING: {
Expand Down Expand Up @@ -274,6 +285,10 @@ export const SignUpRouterMachine = setup({
},
},
on: {
'RESET.STEP': {
target: 'Start',
reenter: true,
},
NEXT: [
{
guard: 'isStatusComplete',
Expand Down Expand Up @@ -307,6 +322,10 @@ export const SignUpRouterMachine = setup({
},
},
on: {
'RESET.STEP': {
target: 'Continue',
reenter: true,
},
NEXT: [
{
guard: 'isStatusComplete',
Expand Down Expand Up @@ -355,6 +374,10 @@ export const SignUpRouterMachine = setup({
},
],
on: {
'RESET.STEP': {
target: 'Verification',
reenter: true,
},
NEXT: [
{
guard: 'isStatusComplete',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import type { TFormMachine } from '~/internals/machines/form';
import type {
BaseRouterContext,
BaseRouterErrorEvent,
BaseRouterFormAttachEvent,
BaseRouterInput,
BaseRouterLoadingEvent,
BaseRouterNextEvent,
BaseRouterPrevEvent,
BaseRouterRedirectEvent,
BaseRouterResetEvent,
BaseRouterResetStepEvent,
BaseRouterSetClerkEvent,
BaseRouterStartEvent,
BaseRouterTransferEvent,
Expand Down Expand Up @@ -41,13 +43,15 @@ export type SignUpRouterSystemId = keyof typeof SignUpRouterSystemId;

// ---------------------------------- Events ---------------------------------- //

export type SignUpRouterFormAttachEvent = BaseRouterFormAttachEvent;
export type SignUpRouterNextEvent = BaseRouterNextEvent<SignUpResource>;
export type SignUpRouterStartEvent = BaseRouterStartEvent;
export type SignUpRouterPrevEvent = BaseRouterPrevEvent;
export type SignUpRouterErrorEvent = BaseRouterErrorEvent;
export type SignUpRouterTransferEvent = BaseRouterTransferEvent;
export type SignUpRouterRedirectEvent = BaseRouterRedirectEvent;
export type SignUpRouterResetEvent = BaseRouterResetEvent;
export type SignUpRouterResetStepEvent = BaseRouterResetStepEvent;
export type SignUpRouterLoadingEvent = BaseRouterLoadingEvent<'start' | 'verifications' | 'continue'>;
export type SignUpRouterSetClerkEvent = BaseRouterSetClerkEvent;

Expand All @@ -60,13 +64,15 @@ export interface SignUpRouterInitEvent extends BaseRouterInput {
export type SignUpRouterNavigationEvents = SignUpRouterStartEvent | SignUpRouterPrevEvent;

export type SignUpRouterEvents =
| SignUpRouterFormAttachEvent
| SignUpRouterInitEvent
| SignUpRouterNextEvent
| SignUpRouterNavigationEvents
| SignUpRouterErrorEvent
| SignUpRouterTransferEvent
| SignUpRouterRedirectEvent
| SignUpRouterResetEvent
| SignUpRouterResetStepEvent
| SignUpRouterLoadingEvent
| SignUpRouterSetClerkEvent;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ import type {
SignInStrategy,
Web3Strategy,
} from '@clerk/types';
import type { ActorRefFrom } from 'xstate';

import type { ClerkElementsError } from '~/internals/errors';
import type { TFormMachine } from '~/internals/machines/form';
import type { ClerkRouter } from '~/react/router';

// ---------------------------------- Events ---------------------------------- //

export type BaseRouterLoadingStep = 'start' | 'verifications' | 'continue' | 'reset-password';

export type BaseRouterNextEvent<T extends ClerkResource> = { type: 'NEXT'; resource?: T };
export type BaseRouterFormAttachEvent = { type: 'FORM.ATTACH'; formRef: ActorRefFrom<TFormMachine> };
export type BaseRouterPrevEvent = { type: 'NAVIGATE.PREVIOUS' };
export type BaseRouterStartEvent = { type: 'NAVIGATE.START' };
export type BaseRouterResetEvent = { type: 'RESET' };
export type BaseRouterResetStepEvent = { type: 'RESET.STEP' };
export type BaseRouterErrorEvent = { type: 'ERROR'; error: Error };
export type BaseRouterTransferEvent = { type: 'TRANSFER' };
export type BaseRouterLoadingEvent<TSteps extends BaseRouterLoadingStep> = (
Expand Down
8 changes: 8 additions & 0 deletions packages/elements/src/react/sign-in/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ function SignInFlowProvider({ children, exampleMode }: SignInFlowProviderProps)
}
});

// Ensure that the latest instantiated formRef is attached to the router
if (formRef && actor.getSnapshot().can({ type: 'RESET.STEP' })) {
actor.send({
type: 'FORM.ATTACH',
formRef,
});
}

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

Expand Down
18 changes: 13 additions & 5 deletions packages/elements/src/react/sign-up/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ type SignUpFlowProviderProps = {
};

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

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

useEffect(() => {
if (!clerk || !router) return;
Expand All @@ -42,14 +42,22 @@ function SignUpFlowProvider({ children, exampleMode }: SignUpFlowProviderProps)
signInPath: SIGN_IN_DEFAULT_BASE_PATH,
};

if (ref.getSnapshot().can(evt)) {
ref.send(evt);
if (actor.getSnapshot().can(evt)) {
actor.send(evt);
}

// Ensure that the latest instantiated formRef is attached to the router
if (formRef && actor.getSnapshot().can({ type: 'RESET.STEP' })) {
actor.send({
type: 'FORM.ATTACH',
formRef,
});
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [clerk, exampleMode, formRef?.id, !!router]);

return isReady ? <SignUpRouterCtx.Provider actorRef={ref}>{children}</SignUpRouterCtx.Provider> : null;
return isReady ? <SignUpRouterCtx.Provider actorRef={actor}>{children}</SignUpRouterCtx.Provider> : null;
}

export type SignUpRootProps = SignUpFlowProviderProps & {
Expand Down