From d53136d59c7d04ddc75fba426daa86113c1759d3 Mon Sep 17 00:00:00 2001 From: Sercan AKMAN Date: Thu, 20 Apr 2023 10:39:05 +0300 Subject: [PATCH] docs(advanced-guides): adding a bit more context to SSG `useIsBrowser` documentation to promote use of --- website/docs/advanced/ssg.mdx | 72 +++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/website/docs/advanced/ssg.mdx b/website/docs/advanced/ssg.mdx index 4f19fc2f32..3c7a993d65 100644 --- a/website/docs/advanced/ssg.mdx +++ b/website/docs/advanced/ssg.mdx @@ -190,8 +190,7 @@ The first client-side render output (in the browser) **must be exactly the same* Usage example: ```jsx -import React from // useState, -// useEffect +import React from // useEffect // useState, 'react'; import useIsBrowser from '@docusaurus/useIsBrowser'; @@ -211,24 +210,6 @@ const MyComponent = () => { ? window.location.href : isFetchingLocationMessage; - /* - const [isFetchingLocation, setIsFetchingLocation] = useState( - location === isFetchingLocationMessage - ) - // Please note that `isFetchingLocation` initial value will be `true` - // even though window is actually defined - // because component has actually rendered once before hydration - // subsequent renders will not update the useState - // and may cause issues with business logic - - // Do this instead - const [isFetchingLocation, setIsFetchingLocation] = useState(true) - - useEffect(() => { - setIsFetchingLocation(location === isFetchingLocationMessage) - }, [isBrowser]) - */ - // highlight-end return (
@@ -242,6 +223,57 @@ const MyComponent = () => { }; ``` +:::caution If your business logic in the component relies on browser specifics to be functional at all, we recommend using [``](../docusaurus-core.mdx#browseronly). The following example will cause business logic issues when used with `useIsBrowser`: + +```jsx +import React, {useState} from 'react'; +import useIsBrowser from '@docusaurus/useIsBrowser'; + +const isFetchingLocationMessage = 'fetching location...'; + +const MyComponent = () => { + const isBrowser = useIsBrowser(); + const location = isBrowser ? window.location.href : isFetchingLocationMessage; + // highlight-start + const [isFetchingLocation, setIsFetchingLocation] = useState( + location === isFetchingLocationMessage, + ); + + // highlight-end + return ( +
+ {/* + This will always print true and will not update. + Component already rendered once and useState referenced the initial value as `true` + */} + {isFetchingLocation} +
+ ); +}; +``` + +To solve this, you can add a `useEffect` to run when hydration has completed: + +```js +useEffect(() => { + setIsFetchingLocation(location === isFetchingLocationMessage); +}, [isBrowser]); +``` + +Or use [``](../docusaurus-core.mdx#browseronly): + +``` +const ParentComponent = () => { + return ( + Loading...
}> + {() => } +
+ ) +} +``` + +::: + ### `useEffect` {#useeffect} Lastly, you can put your logic in `useEffect()` to delay its execution until after first CSR. This is most appropriate if you are only performing side-effects but don't _get_ data from the client state.