mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-19 17:49:19 +02:00
docs(core): explaining the difference between "hydration completion" versus "actually being in the browser environment" in useIsBrowser()
hook
This commit is contained in:
parent
f8edeb0816
commit
948ef8e4f3
1 changed files with 58 additions and 0 deletions
|
@ -433,6 +433,64 @@ const MyComponent = () => {
|
|||
};
|
||||
```
|
||||
|
||||
#### A caveat to know when using `useIsBrowser`
|
||||
|
||||
Because it does not do `typeof windows !== 'undefined'` check but rather checks if the React app has successfully hydrated, the following code will not work as intended:
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
import useIsBrowser from '@docusaurus/useIsBrowser';
|
||||
|
||||
const MyComponent = () => {
|
||||
// highlight-start
|
||||
const isBrowser = useIsBrowser();
|
||||
const url = isBrowser ? new URL(window.location.href) : undefined;
|
||||
const someQueryParam = url?.searchParams.get('someParam');
|
||||
const [someParam, setSomeParam] = useState(someQueryParam || 'fallbackValue');
|
||||
|
||||
// renders fallbackValue instead of the value of someParam query parameter
|
||||
// because the component has already rendered but hydration has not completed
|
||||
// useState references the fallbackValue
|
||||
return <span>{someParam}</span>;
|
||||
// highlight-end
|
||||
};
|
||||
```
|
||||
|
||||
Adding `useIsBrowser()` checks to derived values will have no effect. Wrapping the `<span>` with `<BrowserOnly>` will also have no effect. To have `useState` reference the correct value, which is the value of the `someParam` query parameter, `MyComponent`'s first render should actually happen after `useIsBrowser` returns true. Because you cannot have if statements inside the component before any hooks, you need to resort to doing `useIsBrowser()` in the parent component as such:
|
||||
|
||||
```jsx
|
||||
import React, {useState} from 'react';
|
||||
import useIsBrowser from '@docusaurus/useIsBrowser';
|
||||
|
||||
const MyComponent = () => {
|
||||
const isBrowser = useIsBrowser();
|
||||
const url = isBrowser ? new URL(window.location.href) : undefined;
|
||||
const someQueryParam = url?.searchParams.get('someParam');
|
||||
const [someParam, setSomeParam] = useState(someQueryParam || 'fallbackValue');
|
||||
|
||||
return <span>{someParam}</span>;
|
||||
};
|
||||
|
||||
// highlight-start
|
||||
const MyComponentParent = () => {
|
||||
const isBrowser = useIsBrowser();
|
||||
|
||||
if (!isBrowser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <MyComponent />;
|
||||
};
|
||||
// highlight-end
|
||||
|
||||
export default MyComponentParent;
|
||||
```
|
||||
|
||||
There are a couple more alternative solutions to this problem. However all of them require adding checks in **the parent component**:
|
||||
|
||||
1. You can wrap `<MyComponent />` with [`BrowserOnly`](../docusaurus-core.mdx#browseronly)
|
||||
2. You can use `canUseDOM` from [`ExecutionEnvironment`](../docusaurus-core.mdx#executionenvironment) and `return null` when `canUseDOM` is `false`
|
||||
|
||||
### `useBaseUrl` {#useBaseUrl}
|
||||
|
||||
React hook to prepend your site `baseUrl` to a string.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue