Skip to content

Commit 0c634f6

Browse files
committed
Render session task context for separate components
1 parent fec85d6 commit 0c634f6

File tree

8 files changed

+63
-40
lines changed

8 files changed

+63
-40
lines changed

packages/clerk-js/src/ui/components/SessionTasks/index.tsx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { useClerk } from '@clerk/shared/react';
22
import { eventComponentMounted } from '@clerk/shared/telemetry';
3-
import type { SessionResource } from '@clerk/shared/types';
43
import { useEffect, useRef } from 'react';
54

65
import { Flow } from '@/ui/customizables';
76
import { Card } from '@/ui/elements/Card';
87
import { withCardStateProvider } from '@/ui/elements/contexts';
98
import { LoadingCardContainer } from '@/ui/elements/LoadingCard';
109

11-
import { getTaskEndpoint, INTERNAL_SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks';
10+
import { INTERNAL_SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks';
1211
import {
1312
SessionTasksContext,
1413
TaskChooseOrganizationContext,
@@ -86,7 +85,7 @@ type SessionTasksProps = {
8685
*/
8786
export const SessionTasks = withCardStateProvider(({ redirectUrlComplete }: SessionTasksProps) => {
8887
const clerk = useClerk();
89-
const { navigate, basePath, startPath } = useRouter();
88+
const { navigate } = useRouter();
9089

9190
const currentTaskContainer = useRef<HTMLDivElement>(null);
9291

@@ -121,21 +120,8 @@ export const SessionTasks = withCardStateProvider(({ redirectUrlComplete }: Sess
121120
);
122121
}
123122

124-
const navigateOnSetActive = async ({ session }: { session: SessionResource }) => {
125-
const currentTask = session.currentTask;
126-
if (!currentTask) {
127-
return navigate(redirectUrlComplete);
128-
}
129-
130-
const taskEndpoint = getTaskEndpoint(currentTask);
131-
132-
// Base path is required for virtual routing with start path
133-
// eg: to navigate from /sign-in/factor-one to /sign-in/tasks/choose-organization
134-
return navigate(`/${basePath + startPath + taskEndpoint}`);
135-
};
136-
137123
return (
138-
<SessionTasksContext.Provider value={{ redirectUrlComplete, currentTaskContainer, navigateOnSetActive }}>
124+
<SessionTasksContext.Provider value={{ redirectUrlComplete }}>
139125
<SessionTasksRoutes />
140126
</SessionTasksContext.Provider>
141127
);

packages/clerk-js/src/ui/components/SessionTasks/tasks/TaskChooseOrganization/ChooseOrganizationScreen.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
sharedMainIdentifierSx,
1717
} from '@/ui/common/organizations/OrganizationPreview';
1818
import { organizationListParams, populateCacheUpdateItem } from '@/ui/components/OrganizationSwitcher/utils';
19-
import { useTaskChooseOrganizationContext } from '@/ui/contexts/components/SessionTasks';
19+
import { useSessionTasksContext, useTaskChooseOrganizationContext } from '@/ui/contexts/components/SessionTasks';
2020
import { Col, descriptors, localizationKeys, Text, useLocalizations } from '@/ui/customizables';
2121
import { Action, Actions } from '@/ui/elements/Actions';
2222
import { Card } from '@/ui/elements/Card';
@@ -25,7 +25,6 @@ import { Header } from '@/ui/elements/Header';
2525
import { OrganizationPreview } from '@/ui/elements/OrganizationPreview';
2626
import { useOrganizationListInView } from '@/ui/hooks/useOrganizationListInView';
2727
import { Add } from '@/ui/icons';
28-
import { useRouter } from '@/ui/router';
2928
import { handleError } from '@/ui/utils/errorHandler';
3029

3130
type ChooseOrganizationScreenProps = {
@@ -107,7 +106,7 @@ export const ChooseOrganizationScreen = (props: ChooseOrganizationScreenProps) =
107106
const MembershipPreview = (props: { organization: OrganizationResource }) => {
108107
const { user } = useUser();
109108
const card = useCardState();
110-
const { navigate } = useRouter();
109+
const { navigateOnSetActive } = useSessionTasksContext();
111110
const { redirectUrlComplete } = useTaskChooseOrganizationContext();
112111
const { isLoaded, setActive } = useOrganizationList();
113112
const { t } = useLocalizations();
@@ -121,9 +120,8 @@ const MembershipPreview = (props: { organization: OrganizationResource }) => {
121120
try {
122121
await setActive({
123122
organization,
124-
navigate: async () => {
125-
// TODO(after-auth) ORGS-779 - Handle next tasks
126-
await navigate(redirectUrlComplete);
123+
navigate: async ({ session }) => {
124+
await navigateOnSetActive?.({ session, redirectUrlComplete });
127125
},
128126
});
129127
} catch (err) {

packages/clerk-js/src/ui/components/SessionTasks/tasks/TaskChooseOrganization/CreateOrganizationScreen.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { useOrganizationList } from '@clerk/shared/react';
22
import type { CreateOrganizationParams } from '@clerk/shared/types';
33

44
import { useEnvironment } from '@/ui/contexts';
5-
import { useTaskChooseOrganizationContext } from '@/ui/contexts/components/SessionTasks';
5+
import { useSessionTasksContext, useTaskChooseOrganizationContext } from '@/ui/contexts/components/SessionTasks';
66
import { localizationKeys } from '@/ui/customizables';
77
import { useCardState } from '@/ui/elements/contexts';
88
import { Form } from '@/ui/elements/Form';
99
import { FormButtonContainer } from '@/ui/elements/FormButtons';
1010
import { FormContainer } from '@/ui/elements/FormContainer';
1111
import { Header } from '@/ui/elements/Header';
12-
import { useRouter } from '@/ui/router';
1312
import { createSlug } from '@/ui/utils/createSlug';
1413
import { handleError } from '@/ui/utils/errorHandler';
1514
import { useFormControl } from '@/ui/utils/useFormControl';
@@ -22,7 +21,7 @@ type CreateOrganizationScreenProps = {
2221

2322
export const CreateOrganizationScreen = (props: CreateOrganizationScreenProps) => {
2423
const card = useCardState();
25-
const { navigate } = useRouter();
24+
const { navigateOnSetActive } = useSessionTasksContext();
2625
const { redirectUrlComplete } = useTaskChooseOrganizationContext();
2726
const { createOrganization, isLoaded, setActive } = useOrganizationList({
2827
userMemberships: organizationListParams.userMemberships,
@@ -60,9 +59,8 @@ export const CreateOrganizationScreen = (props: CreateOrganizationScreenProps) =
6059

6160
await setActive({
6261
organization,
63-
navigate: async () => {
64-
// TODO(after-auth) ORGS-779 - Handle next tasks
65-
await navigate(redirectUrlComplete);
62+
navigate: async ({ session }) => {
63+
await navigateOnSetActive?.({ session, redirectUrlComplete });
6664
},
6765
});
6866
} catch (err) {

packages/clerk-js/src/ui/components/SessionTasks/tasks/TaskResetPassword/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ const TaskResetPasswordInternal = () => {
2525

2626
const { t, locale } = useLocalizations();
2727
const { redirectUrlComplete } = useTaskResetPasswordContext();
28-
const { navigateOnSetActive } = useSessionTasksContext();
2928
const { otherSessions } = useMultipleSessions({ user: clerk.user });
3029
const { navigateAfterSignOut, navigateAfterMultiSessionSingleSignOutUrl } = useSignOutContext();
3130
const updatePasswordWithReverification = useReverification(
3231
(user: UserResource, opts: Parameters<UserResource['updatePassword']>) => user.updatePassword(...opts),
3332
);
33+
const { navigateOnSetActive } = useSessionTasksContext();
3434

3535
const handleSignOut = () => {
3636
if (otherSessions.length === 0) {
@@ -94,7 +94,7 @@ const TaskResetPasswordInternal = () => {
9494
await clerk.setActive({
9595
session: clerk.session,
9696
navigate: async ({ session }) => {
97-
await navigateOnSetActive({ session, redirectUrl: redirectUrlComplete });
97+
await navigateOnSetActive?.({ session, redirectUrlComplete });
9898
},
9999
});
100100
} catch (e) {

packages/clerk-js/src/ui/components/SessionTasks/tasks/shared/withTaskGuard.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,18 @@ import { withRedirect } from '@/ui/common';
66
import { useSessionTasksContext } from '@/ui/contexts/components/SessionTasks';
77
import type { AvailableComponentProps } from '@/ui/types';
88

9+
/**
10+
* Triggers a redirect if current task is not the given task key.
11+
*
12+
* If there's a current session, it will redirect to the `redirectUrlComplete` prop.
13+
* If there's no current session, it will redirect to the sign in URL.
14+
*
15+
* @internal
16+
*/
917
export const withTaskGuard = <P extends AvailableComponentProps>(
1018
Component: ComponentType<P>,
1119
taskKey: SessionTask['key'],
12-
) => {
20+
): ((props: P) => null | JSX.Element) => {
1321
const displayName = Component.displayName || Component.name || 'Component';
1422
Component.displayName = displayName;
1523

packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ import {
2828
UserVerificationContext,
2929
WaitlistContext,
3030
} from './components';
31-
import { TaskChooseOrganizationContext, TaskResetPasswordContext } from './components/SessionTasks';
31+
import {
32+
SessionTasksContext,
33+
TaskChooseOrganizationContext,
34+
TaskResetPasswordContext,
35+
} from './components/SessionTasks';
3236

3337
export function ComponentContextProvider({
3438
componentName,
@@ -124,15 +128,19 @@ export function ComponentContextProvider({
124128
<TaskChooseOrganizationContext.Provider
125129
value={{ componentName: 'TaskChooseOrganization', ...(props as TaskChooseOrganizationProps) }}
126130
>
127-
{children}
131+
<SessionTasksContext.Provider value={{ ...(props as TaskChooseOrganizationProps) }}>
132+
{children}
133+
</SessionTasksContext.Provider>
128134
</TaskChooseOrganizationContext.Provider>
129135
);
130136
case 'TaskResetPassword':
131137
return (
132138
<TaskResetPasswordContext.Provider
133139
value={{ componentName: 'TaskResetPassword', ...(props as TaskResetPasswordProps) }}
134140
>
135-
{children}
141+
<SessionTasksContext.Provider value={{ ...(props as TaskResetPasswordProps) }}>
142+
{children}
143+
</SessionTasksContext.Provider>
136144
</TaskResetPasswordContext.Provider>
137145
);
138146
default:

packages/clerk-js/src/ui/contexts/components/SessionTasks.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,45 @@
1+
import type { SessionResource } from '@clerk/shared/types';
12
import { createContext, useContext } from 'react';
23

4+
import { getTaskEndpoint } from '@/core/sessionTasks';
5+
import { useRouter } from '@/ui/router';
6+
37
import type { SessionTasksCtx, TaskChooseOrganizationCtx, TaskResetPasswordCtx } from '../../types';
48

59
export const SessionTasksContext = createContext<SessionTasksCtx | null>(null);
610

7-
export const useSessionTasksContext = (): SessionTasksCtx => {
11+
type SessionTasksContextType = SessionTasksCtx & {
12+
navigateOnSetActive: (opts: { session: SessionResource; redirectUrlComplete: string }) => Promise<unknown>;
13+
};
14+
15+
export const useSessionTasksContext = (): SessionTasksContextType => {
816
const context = useContext(SessionTasksContext);
17+
const { navigate, basePath, startPath } = useRouter();
918

1019
if (context === null) {
1120
throw new Error('Clerk: useSessionTasksContext called outside of the mounted SessionTasks component.');
1221
}
1322

14-
return context;
23+
const navigateOnSetActive = async ({
24+
session,
25+
redirectUrlComplete,
26+
}: {
27+
session: SessionResource;
28+
redirectUrlComplete: string;
29+
}) => {
30+
const currentTask = session.currentTask;
31+
if (!currentTask) {
32+
return navigate(redirectUrlComplete);
33+
}
34+
35+
const taskEndpoint = getTaskEndpoint(currentTask);
36+
37+
// Base path is required for virtual routing with start path
38+
// eg: to navigate from /sign-in/factor-one to /sign-in/tasks/choose-organization
39+
return navigate(`/${basePath + startPath + taskEndpoint}`);
40+
};
41+
42+
return { ...context, navigateOnSetActive };
1543
};
1644

1745
export const TaskChooseOrganizationContext = createContext<TaskChooseOrganizationCtx | null>(null);

packages/clerk-js/src/ui/types.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {
1212
OrganizationProfileProps,
1313
OrganizationSwitcherProps,
1414
PricingTableProps,
15-
SessionResource,
1615
SignInFallbackRedirectUrl,
1716
SignInForceRedirectUrl,
1817
SignInProps,
@@ -144,8 +143,6 @@ export type CheckoutCtx = __internal_CheckoutProps & {
144143

145144
export type SessionTasksCtx = {
146145
redirectUrlComplete: string;
147-
currentTaskContainer?: React.RefObject<HTMLDivElement> | null;
148-
navigateOnSetActive: (opts: { session: SessionResource; redirectUrl: string }) => Promise<unknown>;
149146
};
150147

151148
export type TaskChooseOrganizationCtx = TaskChooseOrganizationProps & {

0 commit comments

Comments
 (0)