From 72d92ed76a6b7fcc9754e4c971001937bda49689 Mon Sep 17 00:00:00 2001 From: sebastienlorber Date: Wed, 25 Oct 2023 17:48:54 +0200 Subject: [PATCH 1/3] fix useWindowSize hydration issues --- .../src/hooks/useWindowSize.ts | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts index a9583b199eb0..e20b2deb993b 100644 --- a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts +++ b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts @@ -28,8 +28,6 @@ function getWindowSize() { : windowSizes.mobile; } -const DevSimulateSSR = process.env.NODE_ENV === 'development' && true; - /** * Gets the current window size as an enum value. We don't want it to return the * actual width value, so that it only re-renders once a breakpoint is crossed. @@ -39,32 +37,25 @@ const DevSimulateSSR = process.env.NODE_ENV === 'development' && true; * may need to render BOTH the mobile/desktop elements (and hide one of them * with mediaquery). We don't return `undefined` on purpose, to make it more * explicit. - * - * In development mode, this hook will still return `"ssr"` for one second, to - * catch potential layout shifts, similar to strict mode calling effects twice. */ export function useWindowSize(): WindowSize { - const [windowSize, setWindowSize] = useState(() => { - if (DevSimulateSSR) { - return 'ssr'; - } - return getWindowSize(); - }); + const [windowSize, setWindowSize] = useState(() => + // It's super important to return a constant value to avoid hydration issues + // see https://github.com/facebook/docusaurus/issues/9379 + 'ssr' + ); useEffect(() => { function updateWindowSize() { setWindowSize(getWindowSize()); } - const timeout = DevSimulateSSR - ? window.setTimeout(updateWindowSize, 1000) - : undefined; + updateWindowSize(); window.addEventListener('resize', updateWindowSize); return () => { window.removeEventListener('resize', updateWindowSize); - clearTimeout(timeout); }; }, []); From cd9b788603391ef6aa012a5ed615723c3d11ba84 Mon Sep 17 00:00:00 2001 From: sebastienlorber Date: Wed, 25 Oct 2023 17:57:02 +0200 Subject: [PATCH 2/3] lint --- .../docusaurus-theme-common/src/hooks/useWindowSize.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts index e20b2deb993b..283b21f0494d 100644 --- a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts +++ b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts @@ -39,10 +39,11 @@ function getWindowSize() { * explicit. */ export function useWindowSize(): WindowSize { - const [windowSize, setWindowSize] = useState(() => - // It's super important to return a constant value to avoid hydration issues - // see https://github.com/facebook/docusaurus/issues/9379 - 'ssr' + const [windowSize, setWindowSize] = useState( + () => + // super important to return a constant value to avoid hydration mismatch + // see https://github.com/facebook/docusaurus/issues/9379 + 'ssr', ); useEffect(() => { From b143f1987a947f10ec6bfd724e2f4636c6cc4fda Mon Sep 17 00:00:00 2001 From: sebastienlorber Date: Wed, 25 Oct 2023 18:01:57 +0200 Subject: [PATCH 3/3] failfast --- packages/docusaurus-theme-common/src/hooks/useWindowSize.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts index 283b21f0494d..06eaef6b3a41 100644 --- a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts +++ b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts @@ -21,7 +21,9 @@ const DesktopThresholdWidth = 996; function getWindowSize() { if (!ExecutionEnvironment.canUseDOM) { - return windowSizes.ssr; + throw new Error( + 'getWindowSize() should only be called after React hydration', + ); } return window.innerWidth > DesktopThresholdWidth ? windowSizes.desktop