Add server-side hydration of initial config+status. Closes #1964

This commit is contained in:
Gabe Kangas
2022-09-10 15:37:07 -07:00
parent 92ef860387
commit 42ff0cdb01
6 changed files with 114 additions and 16 deletions

View File

@@ -1,3 +1,5 @@
/* eslint-disable react/no-danger */
/* eslint-disable react/no-unescaped-entities */
import { Layout } from 'antd';
import { useRecoilValue } from 'recoil';
import Head from 'next/head';
@@ -27,6 +29,11 @@ export const Main: FC = () => {
setupNoLinkReferrer(layoutRef.current);
}, []);
const hydrationScript = `
window.statusHydration = {{.StatusJSON}};
window.configHydration = {{.ServerConfigJSON}};
`;
return (
<>
<Head>
@@ -86,6 +93,7 @@ export const Main: FC = () => {
<meta name="theme-color" content="#ffffff" />
<style>{customStyles}</style>
<script dangerouslySetInnerHTML={{ __html: hydrationScript }} />
</Head>
<ClientConfigStore />

View File

@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { FC, useEffect } from 'react';
import { atom, selector, useRecoilState, useSetRecoilState } from 'recoil';
import { useMachine } from '@xstate/react';
import { makeEmptyClientConfig, ClientConfig } from '../../interfaces/client-config.model';
@@ -170,7 +170,7 @@ function mergeMeta(meta) {
}, {});
}
export const ClientConfigStore = () => {
export const ClientConfigStore: FC = () => {
const [appState, appStateSend, appStateService] = useMachine(appStateModel);
const setChatDisplayName = useSetRecoilState<string>(chatDisplayNameAtom);
@@ -343,6 +343,29 @@ export const ClientConfigStore = () => {
}
};
// Read the config and status on initial load from a JSON string that lives
// in window. This is placed there server-side and allows for fast initial
// load times because we don't have to wait for the API calls to complete.
useEffect(() => {
try {
if ((window as any).configHydration) {
const config = JSON.parse((window as any).configHydration);
setClientConfig(config);
}
} catch (e) {
// console.error('Error parsing config hydration', e);
}
try {
if ((window as any).statusHydration) {
const status = JSON.parse((window as any).statusHydration);
setServerStatus(status);
}
} catch (e) {
// console.error('error parsing status hydration', e);
}
}, []);
useEffect(() => {
updateClientConfig();
handleUserRegistration();