-
Notifications
You must be signed in to change notification settings - Fork 327
/
Copy pathClerkContextProvider.tsx
116 lines (100 loc) · 3.66 KB
/
ClerkContextProvider.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { deriveState } from '@clerk/shared/deriveState';
import { ClientContext, OrganizationProvider, SessionContext, UserContext } from '@clerk/shared/react';
import type { ClientResource, InitialState, Resources } from '@clerk/types';
import React from 'react';
import { IsomorphicClerk } from '../isomorphicClerk';
import type { IsomorphicClerkOptions } from '../types';
import { AuthContext } from './AuthContext';
import { IsomorphicClerkContext } from './IsomorphicClerkContext';
type ClerkContextProvider = {
isomorphicClerkOptions: IsomorphicClerkOptions;
initialState: InitialState | undefined;
children: React.ReactNode;
};
export type ClerkContextProviderState = Resources;
export function ClerkContextProvider(props: ClerkContextProvider) {
const { isomorphicClerkOptions, initialState, children } = props;
const { isomorphicClerk: clerk, loaded: clerkLoaded } = useLoadedIsomorphicClerk(isomorphicClerkOptions);
const [state, setState] = React.useState<ClerkContextProviderState>({
client: clerk.client as ClientResource,
session: clerk.session,
user: clerk.user,
organization: clerk.organization,
});
React.useEffect(() => {
return clerk.addListener(e => setState({ ...e }));
}, []);
const derivedState = deriveState(clerkLoaded, state, initialState);
const clerkCtx = React.useMemo(() => ({ value: clerk }), [clerkLoaded]);
const clientCtx = React.useMemo(() => ({ value: state.client }), [state.client]);
const {
sessionId,
sessionStatus,
session,
userId,
user,
orgId,
actor,
organization,
orgRole,
orgSlug,
orgPermissions,
factorVerificationAge,
} = derivedState;
const authCtx = React.useMemo(() => {
const value = {
sessionId,
sessionStatus,
userId,
actor,
orgId,
orgRole,
orgSlug,
orgPermissions,
factorVerificationAge,
};
return { value };
}, [sessionId, sessionStatus, userId, actor, orgId, orgRole, orgSlug, factorVerificationAge]);
const sessionCtx = React.useMemo(() => ({ value: session }), [sessionId, session]);
const userCtx = React.useMemo(() => ({ value: user }), [userId, user]);
const organizationCtx = React.useMemo(() => {
const value = {
organization: organization,
};
return { value };
}, [orgId, organization]);
return (
// @ts-expect-error value passed is of type IsomorphicClerk where the context expects LoadedClerk
<IsomorphicClerkContext.Provider value={clerkCtx}>
<ClientContext.Provider value={clientCtx}>
<SessionContext.Provider value={sessionCtx}>
<OrganizationProvider {...organizationCtx.value}>
<AuthContext.Provider value={authCtx}>
<UserContext.Provider value={userCtx}>{children}</UserContext.Provider>
</AuthContext.Provider>
</OrganizationProvider>
</SessionContext.Provider>
</ClientContext.Provider>
</IsomorphicClerkContext.Provider>
);
}
const useLoadedIsomorphicClerk = (options: IsomorphicClerkOptions) => {
const [loaded, setLoaded] = React.useState(false);
const isomorphicClerk = React.useMemo(() => IsomorphicClerk.getOrCreateInstance(options), []);
React.useEffect(() => {
void isomorphicClerk.__unstable__updateProps({ appearance: options.appearance });
}, [options.appearance]);
React.useEffect(() => {
void isomorphicClerk.__unstable__updateProps({ options });
}, [options.localization]);
React.useEffect(() => {
isomorphicClerk.addOnLoaded(() => setLoaded(true));
}, []);
React.useEffect(() => {
return () => {
IsomorphicClerk.clearInstance();
setLoaded(false);
};
}, []);
return { isomorphicClerk, loaded };
};