Skip to content

Commit 026ad57

Browse files
authored
chore(clerk-react,astro,vue): Introduce treatPendingAsSignedOut prop to client control components (#5512)
1 parent a8180ce commit 026ad57

File tree

4 files changed

+66
-26
lines changed

4 files changed

+66
-26
lines changed

Diff for: .changeset/red-ducks-hide.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
'@clerk/astro': patch
3+
'@clerk/clerk-react': patch
4+
'@clerk/vue': patch
5+
---
6+
7+
Introduce `treatPendingAsSignedOut` prop to client control components
8+
9+
```tsx
10+
// Children node only mounts when session is active
11+
// Example: Organization selection must be completed if enforced
12+
<SignedIn>
13+
<p>You have selected an organization!</p>
14+
</SignedIn>
15+
```
16+
```tsx
17+
// Children node mounts for both active and pending session
18+
<SignedIn treatPendingAsSignedOut={false}>
19+
<p>You might not have an organization selected</p>
20+
</SignedIn>
21+
```
22+
23+
```tsx
24+
// Children node only mounts when session is active
25+
// Example: Organization selection must be completed if enforced
26+
<Protect>
27+
<p>You have selected an organization!</p>
28+
</Protect>
29+
```
30+
```tsx
31+
// Children node mounts for both active and pending session
32+
<Protect treatPendingAsSignedOut={false}>
33+
<p>You might not have an organization selected</p>
34+
</Protect>
35+
```

Diff for: packages/astro/src/react/controlComponents.tsx

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CheckAuthorizationWithCustomPermissions, HandleOAuthCallbackParams } from '@clerk/types';
1+
import type { HandleOAuthCallbackParams, PendingSessionOptions } from '@clerk/types';
22
import { computed } from 'nanostores';
33
import type { PropsWithChildren } from 'react';
44
import React, { useEffect, useState } from 'react';
@@ -9,21 +9,21 @@ import { useAuth } from './hooks';
99
import type { WithClerkProp } from './utils';
1010
import { withClerk } from './utils';
1111

12-
export function SignedOut(props: PropsWithChildren) {
13-
const { userId } = useAuth();
12+
export function SignedOut({ children, treatPendingAsSignedOut }: PropsWithChildren<PendingSessionOptions>) {
13+
const { userId } = useAuth({ treatPendingAsSignedOut });
1414

1515
if (userId) {
1616
return null;
1717
}
18-
return props.children;
18+
return children;
1919
}
2020

21-
export function SignedIn(props: PropsWithChildren) {
22-
const { userId } = useAuth();
21+
export function SignedIn({ children, treatPendingAsSignedOut }: PropsWithChildren<PendingSessionOptions>) {
22+
const { userId } = useAuth({ treatPendingAsSignedOut });
2323
if (!userId) {
2424
return null;
2525
}
26-
return props.children;
26+
return children;
2727
}
2828

2929
const $isLoadingClerkStore = computed($csrState, state => state.isLoaded);
@@ -69,7 +69,9 @@ export const ClerkLoading = ({ children }: React.PropsWithChildren): JSX.Element
6969
return <>{children}</>;
7070
};
7171

72-
export type ProtectProps = React.PropsWithChildren<_ProtectProps & { fallback?: React.ReactNode }>;
72+
export type ProtectProps = React.PropsWithChildren<
73+
_ProtectProps & { fallback?: React.ReactNode } & PendingSessionOptions
74+
>;
7375

7476
/**
7577
* Use `<Protect/>` in order to prevent unauthenticated or unauthorized users from accessing the children passed to the component.
@@ -83,8 +85,8 @@ export type ProtectProps = React.PropsWithChildren<_ProtectProps & { fallback?:
8385
* <Protect fallback={<p>Unauthorized</p>} />
8486
* ```
8587
*/
86-
export const Protect = ({ children, fallback, ...restAuthorizedParams }: ProtectProps) => {
87-
const { isLoaded, has, userId } = useAuth();
88+
export const Protect = ({ children, fallback, treatPendingAsSignedOut, ...restAuthorizedParams }: ProtectProps) => {
89+
const { isLoaded, has, userId } = useAuth({ treatPendingAsSignedOut });
8890

8991
/**
9092
* Avoid flickering children or fallback while clerk is loading sessionId or userId
@@ -108,7 +110,7 @@ export const Protect = ({ children, fallback, ...restAuthorizedParams }: Protect
108110
* Check against the results of `has` called inside the callback
109111
*/
110112
if (typeof restAuthorizedParams.condition === 'function') {
111-
if (restAuthorizedParams.condition(has as CheckAuthorizationWithCustomPermissions)) {
113+
if (restAuthorizedParams.condition(has)) {
112114
return authorized;
113115
}
114116
return unauthorized;

Diff for: packages/react/src/components/controlComponents.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,31 @@ import type {
44
HandleOAuthCallbackParams,
55
OrganizationCustomPermissionKey,
66
OrganizationCustomRoleKey,
7+
PendingSessionOptions,
78
} from '@clerk/types';
89
import React from 'react';
910

10-
import { useAuthContext } from '../contexts/AuthContext';
1111
import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext';
1212
import { useSessionContext } from '../contexts/SessionContext';
1313
import { useAuth } from '../hooks';
1414
import { useAssertWrappedByClerkProvider } from '../hooks/useAssertWrappedByClerkProvider';
1515
import type { RedirectToSignInProps, RedirectToSignUpProps, WithClerkProp } from '../types';
1616
import { withClerk } from './withClerk';
1717

18-
export const SignedIn = ({ children }: React.PropsWithChildren<unknown>) => {
18+
export const SignedIn = ({ children, treatPendingAsSignedOut }: React.PropsWithChildren<PendingSessionOptions>) => {
1919
useAssertWrappedByClerkProvider('SignedIn');
2020

21-
const { userId } = useAuthContext();
21+
const { userId } = useAuth({ treatPendingAsSignedOut });
2222
if (userId) {
2323
return children;
2424
}
2525
return null;
2626
};
2727

28-
export const SignedOut = ({ children }: React.PropsWithChildren<unknown>) => {
28+
export const SignedOut = ({ children, treatPendingAsSignedOut }: React.PropsWithChildren<PendingSessionOptions>) => {
2929
useAssertWrappedByClerkProvider('SignedOut');
3030

31-
const { userId } = useAuthContext();
31+
const { userId } = useAuth({ treatPendingAsSignedOut });
3232
if (userId === null) {
3333
return children;
3434
}
@@ -79,7 +79,7 @@ export type ProtectProps = React.PropsWithChildren<
7979
}
8080
) & {
8181
fallback?: React.ReactNode;
82-
}
82+
} & PendingSessionOptions
8383
>;
8484

8585
/**
@@ -94,10 +94,10 @@ export type ProtectProps = React.PropsWithChildren<
9494
* <Protect fallback={<p>Unauthorized</p>} />
9595
* ```
9696
*/
97-
export const Protect = ({ children, fallback, ...restAuthorizedParams }: ProtectProps) => {
97+
export const Protect = ({ children, fallback, treatPendingAsSignedOut, ...restAuthorizedParams }: ProtectProps) => {
9898
useAssertWrappedByClerkProvider('Protect');
9999

100-
const { isLoaded, has, userId } = useAuth();
100+
const { isLoaded, has, userId } = useAuth({ treatPendingAsSignedOut });
101101

102102
/**
103103
* Avoid flickering children or fallback while clerk is loading sessionId or userId

Diff for: packages/vue/src/components/controlComponents.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
HandleOAuthCallbackParams,
55
OrganizationCustomPermissionKey,
66
OrganizationCustomRoleKey,
7+
PendingSessionOptions,
78
RedirectOptions,
89
} from '@clerk/types';
910
import { defineComponent } from 'vue';
@@ -13,14 +14,14 @@ import { useClerk } from '../composables/useClerk';
1314
import { useClerkContext } from '../composables/useClerkContext';
1415
import { useClerkLoaded } from '../utils/useClerkLoaded';
1516

16-
export const SignedIn = defineComponent((_, { slots }) => {
17-
const { userId } = useAuth();
17+
export const SignedIn = defineComponent<PendingSessionOptions>(({ treatPendingAsSignedOut }, { slots }) => {
18+
const { userId } = useAuth({ treatPendingAsSignedOut });
1819

1920
return () => (userId.value ? slots.default?.() : null);
2021
});
2122

22-
export const SignedOut = defineComponent((_, { slots }) => {
23-
const { userId } = useAuth();
23+
export const SignedOut = defineComponent<PendingSessionOptions>(({ treatPendingAsSignedOut }, { slots }) => {
24+
const { userId } = useAuth({ treatPendingAsSignedOut });
2425

2526
return () => (userId.value === null ? slots.default?.() : null);
2627
});
@@ -105,7 +106,7 @@ export const AuthenticateWithRedirectCallback = defineComponent((props: HandleOA
105106
return () => null;
106107
});
107108

108-
export type ProtectProps =
109+
export type ProtectProps = (
109110
| {
110111
condition?: never;
111112
role: OrganizationCustomRoleKey;
@@ -125,10 +126,12 @@ export type ProtectProps =
125126
condition?: never;
126127
role?: never;
127128
permission?: never;
128-
};
129+
}
130+
) &
131+
PendingSessionOptions;
129132

130133
export const Protect = defineComponent((props: ProtectProps, { slots }) => {
131-
const { isLoaded, has, userId } = useAuth();
134+
const { isLoaded, has, userId } = useAuth({ treatPendingAsSignedOut: props.treatPendingAsSignedOut });
132135

133136
return () => {
134137
/**

0 commit comments

Comments
 (0)