From ef61d10683ff86dcc3f0e7549ba4588a11a5ce86 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Fri, 2 Jun 2023 19:05:31 +0800 Subject: [PATCH] :bug: fix: fix suspense hydration with ssr --- src/factories/createThemeProvider/ThemeSwitcher.tsx | 12 +++++++++--- src/utils/safeStartTransition.ts | 9 +++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 src/utils/safeStartTransition.ts diff --git a/src/factories/createThemeProvider/ThemeSwitcher.tsx b/src/factories/createThemeProvider/ThemeSwitcher.tsx index 0b4a14d6..378397cc 100644 --- a/src/factories/createThemeProvider/ThemeSwitcher.tsx +++ b/src/factories/createThemeProvider/ThemeSwitcher.tsx @@ -4,6 +4,7 @@ import useMergeValue from 'use-merge-value'; import { ThemeModeContext } from '@/context'; import { BrowserPrefers, ThemeAppearance, ThemeMode, UseTheme } from '@/types'; import { matchBrowserPrefers } from '@/utils/matchBrowserPrefers'; +import { safeStartTransition } from '@/utils/safeStartTransition'; let darkThemeMatch: MediaQueryList; @@ -32,7 +33,9 @@ const ThemeObserver: FC<{ useLayoutEffect(() => { // 如果不是自动,就明确设定亮暗色 if (themeMode !== 'auto') { - setAppearance(themeMode); + safeStartTransition(() => { + setAppearance(themeMode); + }); return; } // 如果是自动的话,则去做一次匹配,并开始监听 @@ -48,7 +51,7 @@ const ThemeObserver: FC<{ }; }, [themeMode]); - useEffect(() => { + useLayoutEffect(() => { if (!darkThemeMatch) { darkThemeMatch = matchBrowserPrefers('dark'); } @@ -117,7 +120,10 @@ const ThemeSwitcher: FC = memo( // Wait until after client-side hydration to show useEffect(() => { - setStartObserver(true); + // 兼容 React18 的 Suspense 问题 + safeStartTransition(() => { + setStartObserver(true); + }); }, []); return ( diff --git a/src/utils/safeStartTransition.ts b/src/utils/safeStartTransition.ts new file mode 100644 index 00000000..d2ef0e71 --- /dev/null +++ b/src/utils/safeStartTransition.ts @@ -0,0 +1,9 @@ +import { startTransition, TransitionFunction } from 'react'; + +export const safeStartTransition = (func: TransitionFunction) => { + if (typeof startTransition === 'function') { + startTransition(func); + } else { + func(); + } +};