mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-22 20:01:57 +00:00
[Beta] Edits to hydrateRoot
This commit is contained in:
@@ -102,15 +102,18 @@ React can recover from some hydration errors, but **you must fix them like other
|
||||
|
||||
Apps fully built with React can render the entire document from the root component, including the [`<html>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html) tag:
|
||||
|
||||
```js {3,10}
|
||||
```js {3,13}
|
||||
function App() {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles.css"></link>
|
||||
<title>My app</title>
|
||||
</head>
|
||||
<body>
|
||||
<Page />
|
||||
<Router />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
@@ -119,18 +122,107 @@ function App() {
|
||||
|
||||
To hydrate the entire document, pass the [`document`](https://developer.mozilla.org/en-US/docs/Web/API/Window/document) global as the first argument to `hydrateRoot`:
|
||||
|
||||
```js {5}
|
||||
```js {4}
|
||||
import { hydrateRoot } from 'react-dom/client';
|
||||
import App from './App.js';
|
||||
|
||||
hydrateRoot(
|
||||
document,
|
||||
<App />
|
||||
);
|
||||
hydrateRoot(document, <App />);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Suppressing unavoidable hydration mismatch errors {/*suppressing-unavoidable-hydration-mismatch-errors*/}
|
||||
|
||||
If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the hydration mismatch warning.
|
||||
|
||||
To silence hydration warnings on an element, add `suppressHydrationWarning={true}`:
|
||||
|
||||
<Sandpack>
|
||||
|
||||
```html public/index.html
|
||||
<!--
|
||||
HTML content inside <div id="root">...</div>
|
||||
was generated from App by react-dom/server.
|
||||
-->
|
||||
<div id="root"><h1>Current Date: <!-- -->01/01/2020</h1></div>
|
||||
```
|
||||
|
||||
```js index.js
|
||||
import './styles.css';
|
||||
import { hydrateRoot } from 'react-dom/client';
|
||||
import App from './App.js';
|
||||
|
||||
hydrateRoot(document.getElementById('root'), <App />);
|
||||
```
|
||||
|
||||
```js App.js active
|
||||
export default function App() {
|
||||
return (
|
||||
<h1 suppressHydrationWarning={true}>
|
||||
Current Date: {new Date().toLocaleDateString()}
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
</Sandpack>
|
||||
|
||||
This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates.
|
||||
|
||||
---
|
||||
|
||||
### Handling different client and server content {/*handling-different-client-and-server-content*/}
|
||||
|
||||
If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a [state variable](/apis/react/useState) like `isClient`, which you can set to `true` in an [Effect](/apis/react/useEffect):
|
||||
|
||||
<Sandpack>
|
||||
|
||||
```html public/index.html
|
||||
<!--
|
||||
HTML content inside <div id="root">...</div>
|
||||
was generated from App by react-dom/server.
|
||||
-->
|
||||
<div id="root"><h1>Is Server</h1></div>
|
||||
```
|
||||
|
||||
```js index.js
|
||||
import './styles.css';
|
||||
import { hydrateRoot } from 'react-dom/client';
|
||||
import App from './App.js';
|
||||
|
||||
hydrateRoot(document.getElementById('root'), <App />);
|
||||
```
|
||||
|
||||
```js App.js active
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function App() {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<h1>
|
||||
{isClient ? 'Is Client' : 'Is Server'}
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
</Sandpack>
|
||||
|
||||
This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration.
|
||||
|
||||
<Pitfall>
|
||||
|
||||
This approach makes hydration slower because your components have to render twice. Be mindful of the user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so rendering a different UI immediately after hydration may also feel jarring to the user.
|
||||
|
||||
</Pitfall>
|
||||
|
||||
---
|
||||
|
||||
### Updating a hydrated root component {/*updating-a-hydrated-root-component*/}
|
||||
|
||||
After the root has finished hydrating, you can call [`root.render`](#root-render) to update the root React component. **Unlike with [`createRoot`](/apis/react-dom/client/createRoot), you don't usually need to do this because the initial content was already rendered as HTML.**
|
||||
@@ -179,8 +271,8 @@ export default function App({counter}) {
|
||||
|
||||
It is uncommon to call [`root.render`](#root-render) on a hydrated root. Usually, you'll [update state](/apis/react/useState) inside one of the components instead.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Reference {/*reference*/}
|
||||
|
||||
### `hydrateRoot(domNode, options?)` {/*hydrateroot*/}
|
||||
|
||||
@@ -74,7 +74,7 @@ For more information on hydration, see the docs for [`hydrateRoot`.](/apis/react
|
||||
|
||||
---
|
||||
|
||||
### Unavoidable hydration mismatches {/*avoiding-unavoidable-hydration-mismatches*/}
|
||||
### Suppressing unavoidable hydration mismatch errors {/*suppressing-unavoidable-hydration-mismatch-errors*/}
|
||||
|
||||
If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the hydration mismatch warning.
|
||||
|
||||
@@ -101,11 +101,9 @@ hydrate(<App />, document.getElementById('root'));
|
||||
```js App.js active
|
||||
export default function App() {
|
||||
return (
|
||||
<>
|
||||
<h1 suppressHydrationWarning={true}>
|
||||
Current Date: {new Date().toLocaleDateString()}
|
||||
</h1>
|
||||
</>
|
||||
<h1 suppressHydrationWarning={true}>
|
||||
Current Date: {new Date().toLocaleDateString()}
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -114,6 +112,8 @@ export default function App() {
|
||||
|
||||
This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates.
|
||||
|
||||
---
|
||||
|
||||
### Handling different client and server content {/*handling-different-client-and-server-content*/}
|
||||
|
||||
If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a [state variable](/apis/react/useState) like `isClient`, which you can set to `true` in an [effect](/apis/react/useEffect):
|
||||
@@ -160,15 +160,15 @@ This way the initial render pass will render the same content as the server, avo
|
||||
|
||||
<Pitfall>
|
||||
|
||||
This approach will make your components slower because they have to render twice, so use it with caution.
|
||||
|
||||
Remember to be mindful of user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so if you render something different in the client-only pass, the transition can be jarring. However, if executed well, it may be beneficial to render a “shell” of the application on the server, and only show some of the extra widgets on the client. To learn how to do this without getting the markup mismatch issues, refer to the explanation in the previous paragraph.
|
||||
This approach makes hydration slower because your components have to render twice. Be mindful of the user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so rendering a different UI immediately after hydration may also feel jarring to the user.
|
||||
|
||||
</Pitfall>
|
||||
|
||||
---
|
||||
|
||||
## Reference {/*reference*/}
|
||||
|
||||
### `hydrate(reactNode, domNode, callback?)` {/*hydrate-root*/}
|
||||
### `hydrate(reactNode, domNode, callback?)` {/*hydrate*/}
|
||||
|
||||
<Deprecated>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user