-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathFronteggProviderNoSSR.tsx
More file actions
109 lines (97 loc) · 3.34 KB
/
Copy pathFronteggProviderNoSSR.tsx
File metadata and controls
109 lines (97 loc) · 3.34 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
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
'use client';
import { AppHolder, FronteggApp, initialize } from '@frontegg/js';
import { FronteggStoreProvider } from '@frontegg/react-hooks';
import { ContextHolder, ContextOptions } from '@frontegg/rest-api';
import { FronteggAppOptions } from '@frontegg/types';
import { NextRouter, useRouter } from 'next/router';
import React, { FC, PropsWithChildren, ReactNode, useEffect, useRef } from 'react';
import AppContext from '../common/AppContext';
import useOnRedirectTo from '../utils/useOnRedirectTo';
import ExpireInListener from './ExpireInListener';
import { createStore, FronteggStore } from '@frontegg/redux-store';
import NoSSRStoreHolder from './NoSSRStoreHolder';
export type FronteggProviderNoSSRProps = PropsWithChildren<FronteggAppOptions>;
type ConnectorProps = PropsWithChildren<FronteggAppOptions> & {
alwaysVisibleChildren?: ReactNode;
router: NextRouter;
appName?: string;
};
const Connector: FC<ConnectorProps> = (_props) => {
const { router, appName, hostedLoginBox, customLoginBox, ...props } = _props;
const baseName = props.basename ?? router.basePath;
const storeHolderRef = useRef<{ store?: FronteggStore }>({});
const onRedirectTo = useOnRedirectTo(baseName, router, props.authOptions?.routes);
const contextOptions: ContextOptions = {
requestCredentials: 'include',
...props.contextOptions,
};
const storeHolder = NoSSRStoreHolder.getInstance() ?? storeHolderRef.current;
let sharedStore = storeHolder.store;
if (!sharedStore) {
sharedStore = createStore({
context: contextOptions,
storeHolder,
previewMode: props.previewMode,
name: appName ?? 'default',
urlStrategy: props.urlStrategy,
builderMode: false,
initialState: {
auth: {
...props.authOptions,
onRedirectTo,
},
},
});
storeHolder.store = sharedStore;
storeHolderRef.current.store = sharedStore;
}
let app: FronteggApp;
try {
app = AppHolder.getInstance(appName ?? 'default');
app.store = sharedStore;
} catch (e) {
app = initialize(
{
...props,
store: sharedStore,
hostedLoginBox: hostedLoginBox ?? false,
basename: props.basename ?? baseName,
authOptions: {
...props.authOptions,
onRedirectTo,
},
contextOptions,
onRedirectTo,
},
appName ?? 'default'
);
app.store.dispatch({ type: 'auth/requestAuthorize', payload: true });
}
ContextHolder.for(appName ?? 'default').setOnRedirectTo(onRedirectTo);
return (
<AppContext.Provider value={app}>
{/* React.createElement + cast: FC from @frontegg/react-hooks doesn't satisfy strict React 18 JSX typings (ReactNode vs ReactPortal). JSX would cause TS2786. */}
{React.createElement(FronteggStoreProvider as React.ComponentType<any>, {
...props,
app,
children: props.children,
})}
</AppContext.Provider>
);
};
const FronteggNextJSProvider: FC<FronteggProviderNoSSRProps> = (props) => {
const router = useRouter();
return (
<Connector {...props} router={router}>
<ExpireInListener />
{props.children}
</Connector>
);
};
export const FronteggProviderNoSSR: FC<FronteggProviderNoSSRProps> = (props) => {
return (
<FronteggNextJSProvider {...props} framework={'nextjs'}>
{props.children}
</FronteggNextJSProvider>
);
};