-
Notifications
You must be signed in to change notification settings - Fork 446
Expand file tree
/
Copy pathClerkProvider.tsx
More file actions
73 lines (60 loc) · 2.83 KB
/
ClerkProvider.tsx
File metadata and controls
73 lines (60 loc) · 2.83 KB
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
import { ClerkContextProvider } from '@clerk/shared/react';
import React from 'react';
import { multipleClerkProvidersError } from '../errors/messages';
import { IsomorphicClerk } from '../isomorphicClerk';
import type { ClerkProviderProps, IsomorphicClerkOptions, Ui } from '../types';
import { mergeWithEnv, withMaxAllowedInstancesGuard } from '../utils';
import { IS_REACT_SHARED_VARIANT_COMPATIBLE } from '../utils/versionCheck';
function ClerkProviderBase<TUi extends Ui>(props: ClerkProviderProps<TUi>) {
const { initialState, children, ...restIsomorphicClerkOptions } = props;
// Merge options with environment variable fallbacks (supports Vite's VITE_CLERK_* env vars)
const mergedOptions = mergeWithEnv(restIsomorphicClerkOptions as unknown as IsomorphicClerkOptions);
const { isomorphicClerk, clerkStatus } = useLoadedIsomorphicClerk(mergedOptions);
return (
<ClerkContextProvider
initialState={initialState}
// @ts-expect-error - Fixme!
clerk={isomorphicClerk}
clerkStatus={clerkStatus}
>
{children}
</ClerkContextProvider>
);
}
const ClerkProvider = withMaxAllowedInstancesGuard(ClerkProviderBase, 'ClerkProvider', multipleClerkProvidersError);
ClerkProvider.displayName = 'ClerkProvider';
export { ClerkProvider };
// Default clerkUIVariant based on React version compatibility.
// Computed once at module level for optimal performance.
const DEFAULT_CLERK_UI_VARIANT = IS_REACT_SHARED_VARIANT_COMPATIBLE ? ('shared' as const) : ('' as const);
const useLoadedIsomorphicClerk = (mergedOptions: IsomorphicClerkOptions) => {
// Merge default clerkUIVariant with user options.
// User-provided options spread last to allow explicit overrides.
// The shared variant expects React to be provided via globalThis.__clerkSharedModules
// (set up by @clerk/ui/register import), which reduces bundle size.
const optionsWithDefaults = React.useMemo(
() => ({
clerkUIVariant: DEFAULT_CLERK_UI_VARIANT,
...mergedOptions,
}),
[mergedOptions],
);
const isomorphicClerkRef = React.useRef(IsomorphicClerk.getOrCreateInstance(optionsWithDefaults));
const [clerkStatus, setClerkStatus] = React.useState(isomorphicClerkRef.current.status);
React.useEffect(() => {
void isomorphicClerkRef.current.__internal_updateProps({ appearance: mergedOptions.appearance });
}, [mergedOptions.appearance]);
React.useEffect(() => {
void isomorphicClerkRef.current.__internal_updateProps({ options: mergedOptions });
}, [mergedOptions.localization]);
React.useEffect(() => {
isomorphicClerkRef.current.on('status', setClerkStatus);
return () => {
if (isomorphicClerkRef.current) {
isomorphicClerkRef.current.off('status', setClerkStatus);
}
IsomorphicClerk.clearInstance();
};
}, []);
return { isomorphicClerk: isomorphicClerkRef.current, clerkStatus };
};