diff --git a/apps/web/src/pages/_app.tsx b/apps/web/src/pages/_app.tsx
index cadf6ca02d..77f360a433 100644
--- a/apps/web/src/pages/_app.tsx
+++ b/apps/web/src/pages/_app.tsx
@@ -16,14 +16,13 @@ import { ModalProvider } from '@/store/globalModal';
// import AppStateProvider2 from '@/providers/app-state-provider2/provider';
import { useRouter } from 'next/router';
-import { useEffect } from 'react';
-import { useAppState } from '@/providers/app-state-provider';
+import { Suspense, useEffect } from 'react';
import { PageLoading } from '@/components/loading';
import Head from 'next/head';
import '@affine/i18n';
import { useTranslation } from '@affine/i18n';
import React from 'react';
-import { GlobalAppProvider } from '@/store/app';
+import { DataCenterLoader, GlobalAppProvider } from '@/store/app';
const ThemeProvider = dynamic(() => import('@/providers/ThemeProvider'), {
ssr: false,
@@ -80,7 +79,13 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
{NoNeedAppStatePageList.includes(router.route) ? (
getLayout()
) : (
- {getLayout()}
+ }>
+ {/* we should put this before every component in case of they read a null value */}
+
+
+ {getLayout()}
+
+
)}
@@ -90,15 +95,13 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
const AppDefender = ({ children }: PropsWithChildren) => {
const router = useRouter();
- const { synced } = useAppState();
-
useEffect(() => {
if (['/index.html', '/'].includes(router.asPath)) {
router.replace('/workspace');
}
}, [router]);
- return
;
+ return <>{children}>;
};
export default App;
diff --git a/apps/web/src/providers/app-state-provider/Provider.tsx b/apps/web/src/providers/app-state-provider/Provider.tsx
index 285dfd8d3d..80b42e4d30 100644
--- a/apps/web/src/providers/app-state-provider/Provider.tsx
+++ b/apps/web/src/providers/app-state-provider/Provider.tsx
@@ -45,21 +45,14 @@ export const AppStateProvider = ({
const onceRef = useRef(true);
const dataCenter = useGlobalState(store => store.dataCenter);
- useEffect(() => {
- if (dataCenter !== null) {
- if (onceRef.current) {
- setAppState({
- workspaceList: dataCenter.workspaces,
- currentWorkspace: null,
- pageList: [],
- synced: true,
- });
- onceRef.current = false;
- } else {
- console.warn('dataCenter Effect called twice. Please fix this ASAP');
- }
- }
- }, [dataCenter]);
+ if (onceRef.current && dataCenter) {
+ setAppState({
+ workspaceList: dataCenter.workspaces,
+ currentWorkspace: null,
+ pageList: [],
+ });
+ onceRef.current = false;
+ }
useEffect(() => {
// FIXME: onWorkspacesChange should have dispose function
diff --git a/apps/web/src/providers/app-state-provider/interface.ts b/apps/web/src/providers/app-state-provider/interface.ts
index e1a81ca041..1cd54018f2 100644
--- a/apps/web/src/providers/app-state-provider/interface.ts
+++ b/apps/web/src/providers/app-state-provider/interface.ts
@@ -18,7 +18,6 @@ export type AppStateValue = {
workspaceList: WorkspaceUnit[];
currentWorkspace: WorkspaceUnit | null;
pageList: PageMeta[];
- synced: boolean;
blobDataSynced?: boolean;
};
diff --git a/apps/web/src/store/app/index.tsx b/apps/web/src/store/app/index.tsx
index 60bb9abbda..8ea54ed60f 100644
--- a/apps/web/src/store/app/index.tsx
+++ b/apps/web/src/store/app/index.tsx
@@ -1,5 +1,5 @@
import type React from 'react';
-import { createContext, useContext, useEffect, useMemo, useRef } from 'react';
+import { createContext, useContext, useMemo } from 'react';
import { createStore, StateCreator, useStore } from 'zustand';
import { combine, subscribeWithSelector } from 'zustand/middleware';
import type { UseBoundStore } from 'zustand/react';
@@ -27,6 +27,7 @@ export type GlobalActionsCreator = StateCreator<
export interface GlobalState extends BlockSuiteState, UserState {
readonly dataCenter: DataCenter;
+ readonly dataCenterPromise: Promise;
}
export interface GlobalActions extends BlockSuiteActions, UserActions {}
@@ -40,6 +41,8 @@ const create = () =>
...createUserState(),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
dataCenter: null!,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ dataCenterPromise: null!,
},
/* deepscan-disable TOO_MANY_ARGS */
(set, get, api) => ({
@@ -71,27 +74,25 @@ export const useGlobalState: UseBoundStore = ((
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any;
-function DataCenterSideEffect() {
- const onceRef = useRef(true);
+export function DataCenterLoader() {
+ const dataCenter = useGlobalState(store => store.dataCenter);
+ const dataCenterPromise = useGlobalState(store => store.dataCenterPromise);
const api = useGlobalStateApi();
- useEffect(() => {
- async function init() {
- const dataCenterPromise = getDataCenter();
- dataCenterPromise.then(async dataCenter => {
- // Ensure datacenter has at least one workspace
- if (dataCenter.workspaces.length === 0) {
- await createDefaultWorkspace(dataCenter);
- }
- api.setState({ dataCenter });
- });
- }
- if (onceRef.current) {
- onceRef.current = false;
- init().then(() => {
- console.log('datacenter init success');
- });
- }
- }, [api]);
+ if (!dataCenter && !dataCenterPromise) {
+ const promise = getDataCenter();
+ api.setState({ dataCenterPromise: promise });
+ promise.then(async dataCenter => {
+ // Ensure datacenter has at least one workspace
+ if (dataCenter.workspaces.length === 0) {
+ await createDefaultWorkspace(dataCenter);
+ }
+ api.setState({ dataCenter });
+ });
+ throw promise;
+ }
+ if (!dataCenter) {
+ throw dataCenterPromise;
+ }
return null;
}
@@ -99,7 +100,6 @@ export const GlobalAppProvider: React.FC =
function ModelProvider({ children }) {
return (
create(), [])}>
-
{children}
);
diff --git a/packages/data-center/src/provider/local/utils.ts b/packages/data-center/src/provider/local/utils.ts
index 3788014105..2bf7fd06f4 100644
--- a/packages/data-center/src/provider/local/utils.ts
+++ b/packages/data-center/src/provider/local/utils.ts
@@ -29,8 +29,9 @@ export const createWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => {
await setDefaultAvatar(blocksuiteWorkspace);
workspaceUnit.update({ avatar: blocksuiteWorkspace.meta.avatar });
}
-
- await writeUpdatesToLocal(blocksuiteWorkspace);
+ if (typeof window !== 'undefined') {
+ await writeUpdatesToLocal(blocksuiteWorkspace);
+ }
workspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
diff --git a/packages/data-center/src/utils/index.ts b/packages/data-center/src/utils/index.ts
index 5c93abd900..7e401d68a3 100644
--- a/packages/data-center/src/utils/index.ts
+++ b/packages/data-center/src/utils/index.ts
@@ -11,6 +11,7 @@ export const createBlocksuiteWorkspace = (
return new BlocksuiteWorkspace({
room: workspaceId,
defaultFlags: { enable_slash_menu: true },
+ isSSR: typeof window === 'undefined',
...workspaceOption,
})
.register(builtInSchemas)