mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-04 10:27:52 +02:00
docs(advanced-guides): adding a bit more context to SSG useIsBrowser
documentation to promote use of <BrowserOnly>
This commit is contained in:
parent
6206a99c10
commit
d53136d59c
1 changed files with 52 additions and 20 deletions
|
@ -190,8 +190,7 @@ The first client-side render output (in the browser) **must be exactly the same*
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import React from // useState,
|
import React from // useEffect // useState,
|
||||||
// useEffect
|
|
||||||
'react';
|
'react';
|
||||||
import useIsBrowser from '@docusaurus/useIsBrowser';
|
import useIsBrowser from '@docusaurus/useIsBrowser';
|
||||||
|
|
||||||
|
@ -211,24 +210,6 @@ const MyComponent = () => {
|
||||||
? window.location.href
|
? window.location.href
|
||||||
: isFetchingLocationMessage;
|
: 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
|
// highlight-end
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -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 [`<BrowserOnly>`](../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 (
|
||||||
|
<div>
|
||||||
|
{/*
|
||||||
|
This will always print true and will not update.
|
||||||
|
Component already rendered once and useState referenced the initial value as `true`
|
||||||
|
*/}
|
||||||
|
{isFetchingLocation}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
To solve this, you can add a `useEffect` to run when hydration has completed:
|
||||||
|
|
||||||
|
```js
|
||||||
|
useEffect(() => {
|
||||||
|
setIsFetchingLocation(location === isFetchingLocationMessage);
|
||||||
|
}, [isBrowser]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use [`<BrowserOnly>`](../docusaurus-core.mdx#browseronly):
|
||||||
|
|
||||||
|
```
|
||||||
|
const ParentComponent = () => {
|
||||||
|
return (
|
||||||
|
<BrowserOnly fallback={<div>Loading...</div>}>
|
||||||
|
{() => <MyComponent />}
|
||||||
|
</BrowserOnly>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
### `useEffect` {#useeffect}
|
### `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.
|
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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue