From 07259a7635e876628415a6b3bd5af4a9dee9bb8e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 1 Dec 2023 21:42:37 +0100 Subject: [PATCH] Fix accounts under ssr --- front/apps/web/next.config.js | 1 + front/apps/web/src/pages/_app.tsx | 21 ++++++----- front/packages/models/src/account-internal.ts | 4 +-- front/packages/models/src/accounts.tsx | 35 ++++++++++++++++--- front/packages/models/src/login.ts | 2 +- 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/front/apps/web/next.config.js b/front/apps/web/next.config.js index 23f0f1a7..94a3ddec 100755 --- a/front/apps/web/next.config.js +++ b/front/apps/web/next.config.js @@ -98,6 +98,7 @@ const nextConfig = { "react-native-web", "react-native-svg", "react-native-reanimated", + "react-native-mmkv", "moti", "yoshiki", "@expo/vector-icons", diff --git a/front/apps/web/src/pages/_app.tsx b/front/apps/web/src/pages/_app.tsx index f41c10dc..0e666252 100755 --- a/front/apps/web/src/pages/_app.tsx +++ b/front/apps/web/src/pages/_app.tsx @@ -109,7 +109,7 @@ const YoshikiDebug = ({ children }: { children: JSX.Element }) => { const App = ({ Component, pageProps }: AppProps) => { const [queryClient] = useState(() => createQueryClient()); - const { queryState, token, randomItems, ...props } = superjson.deserialize( + const { queryState, token, randomItems, account, ...props } = superjson.deserialize( pageProps ?? { json: {} }, ); const layoutInfo = (Component as QueryPage).getLayout ?? (({ page }) => page); @@ -132,7 +132,7 @@ const App = ({ Component, pageProps }: AppProps) => { - + @@ -160,27 +160,32 @@ const App = ({ Component, pageProps }: AppProps) => { }; App.getInitialProps = async (ctx: AppContext) => { - const account = readAccountCookie(ctx.ctx.req?.headers.cookie); const appProps = await NextApp.getInitialProps(ctx); const Component = ctx.Component as QueryPage; + const items = arrayShuffle(Component.randomItems ?? []); + appProps.pageProps.randomItems = { + [Component.displayName!]: items, + }; + + if (typeof window !== "undefined") return { pageProps: superjson.serialize(appProps.pageProps) }; + + const getUrl = Component.getFetchUrls; const getLayoutUrl = Component.getLayout && "Layout" in Component.getLayout ? Component.getLayout.Layout.getFetchUrls : Component.getLayout?.getFetchUrls; - - const items = arrayShuffle(Component.randomItems ?? []); - appProps.pageProps.randomItems = { - [Component.displayName!]: items, - }; const urls: QueryIdentifier[] = [ ...(getUrl ? getUrl(ctx.router.query as any, items) : []), ...(getLayoutUrl ? getLayoutUrl(ctx.router.query as any, items) : []), ]; + + const account = readAccountCookie(ctx.ctx.req?.headers.cookie); const [authToken, token] = await getTokenWJ(account ?? null); appProps.pageProps.queryState = await fetchQuery(urls, authToken); appProps.pageProps.token = token; + appProps.pageProps.account = account; return { pageProps: superjson.serialize(appProps.pageProps) }; }; diff --git a/front/packages/models/src/account-internal.ts b/front/packages/models/src/account-internal.ts index b5b97a9d..802716ff 100644 --- a/front/packages/models/src/account-internal.ts +++ b/front/packages/models/src/account-internal.ts @@ -35,9 +35,9 @@ const writeAccounts = (accounts: Account[]) => { }; export const setAccountCookie = (account?: Account) => { - const value = JSON.stringify(account); + let value = JSON.stringify(account); // Remove illegal values from json. There should not be one in the account anyways. - value.replaceAll(";", ""); + value = value?.replaceAll(";", ""); const d = new Date(); // A year d.setTime(d.getTime() + 365 * 24 * 60 * 60 * 1000); diff --git a/front/packages/models/src/accounts.tsx b/front/packages/models/src/accounts.tsx index af3dd37b..31049734 100644 --- a/front/packages/models/src/accounts.tsx +++ b/front/packages/models/src/accounts.tsx @@ -53,16 +53,43 @@ export const ConnectionErrorContext = createContext<{ retry?: () => void; }>({ error: null }); -export const AccountProvider = ({ children }: { children: ReactNode }) => { +/* eslint-disable react-hooks/rules-of-hooks */ +export const AccountProvider = ({ + children, + ssrAccount, +}: { + children: ReactNode; + ssrAccount?: Account; +}) => { + if (Platform.OS === "web" && typeof window === "undefined") { + const accs = ssrAccount + ? [{ ...ssrAccount, selected: true, select: () => { }, remove: () => { } }] + : []; + return ( + + { + queryClient.invalidateQueries({ queryKey: ["auth", "me"] }); + }, + }} + > + {children} + + + ); + } + const [accStr] = useMMKVString("accounts"); - const acc = z.array(AccountP).parse(accStr); + const acc = accStr ? z.array(AccountP).parse(accStr) : null; const accounts = useMemo( () => - acc.map((account) => ({ + acc?.map((account) => ({ ...account, select: () => updateAccount(account.id, { ...account, selected: true }), remove: () => removeAccounts((x) => x.id == x.id), - })), + })) ?? [], [acc], ); diff --git a/front/packages/models/src/login.ts b/front/packages/models/src/login.ts index 099e23ea..a3afc2c9 100644 --- a/front/packages/models/src/login.ts +++ b/front/packages/models/src/login.ts @@ -60,7 +60,7 @@ export const login = async ( }; export const getTokenWJ = async (account?: Account | null): Promise<[string, Token] | [null, null]> => { - if (account === null) + if (account === undefined) account = getCurrentAccount(); if (!account) return [null, null];