hydrateRoot
hydrateRoot
дозволяє відображати React-компоненти всередині DOM-вузла браузера, HTML-вміст якого був попередньо згенерований react-dom/server
.
const root = hydrateRoot(domNode, reactNode, options?)
Посилання
hydrateRoot(domNode, reactNode, options?)
Виклик hydrateRoot
для "приєднання" React до існуючого HTML, який вже було відрендерено React у серверному середовищі.
import { hydrateRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = hydrateRoot(domNode, reactNode);
React приєднається до HTML, що існує всередині domNode
, і візьме на себе управління DOM всередині нього. Застосунок, повністю побудований на React, зазвичай має лише один виклик hydrateRoot
з кореневого компонента.
Дивіться більше прикладів нижче.
Параметри
domNode
: Елемент DOM, який було відрендерено як кореневий елемент на сервері.reactNode
: "Вузол React", який використовується для рендерингу існуючого HTML. Зазвичай це буде фрагмент JSX на кшталт<App />
, який було відрендерено методомReactDOM Server
, наприклад,renderToPipeableStream(<App />)
.опція
опцій
: Об'єкт з опціями для цього кореня React.- optional
onRecoverableError
: Зворотний виклик, що виконується, коли React автоматично відновлюється після помилок. .
- optional
identifierPrefix
: Рядковий префікс, який React використовує для ідентифікаторів, згенерованихuseId
. Корисно для уникнення конфліктів при використанні декількох коренів на одній сторінці. Має бути той самий префікс, що використовується на сервері.
- optional
Повернення
hydrateRoot
повертає об'єкт з двома методами: render
та unmount
.
Застереження
hydrateRoot()
очікує, що відрендерений вміст буде ідентичним вмісту, що відрендовується на сервері. Невідповідності слід розглядати як помилки і виправляти їх.- У режимі розробки React попереджає про невідповідності під час гідратації. Немає жодних гарантій, що відмінності в атрибутах будуть виправлені у разі виявлення невідповідностей. Це важливо з міркувань продуктивності, оскільки в більшості застосунків розбіжності трапляються рідко, і тому перевірка всієї розмітки була б надто складною.
- Ймовірно, у вашому застосунку буде лише один виклик
hydrateRoot
. Якщо ви використовуєте фреймворк, він може виконати цей виклик за вас. - Якщо ваш застосунок рендериться клієнтом без попереднього рендерингу HTML, використання
hydrateRoot()
не підтримується. Замість цього використовуйтеcreateRoot()
.
root.render(reactNode)
Викличте root.render
, щоб оновити React-компонент всередині гідратованого кореня React для DOM-елемента браузера.
root.render(<App />);
React оновить <App />
у гідратованому корені
.
Дивіться більше прикладів нижче.
Параметри
reactNode
: "Вузол React", який ви хочете оновити. Зазвичай це буде фрагмент JSX на кшталт<App />
, але ви також можете передати React-елемент, побудований за допомогоюcreateElement()
, рядок, число,null
абоundefined
.
Повернення
root.render
повертає undefined
.
Застереження
- Якщо ви викликаєте
root.render
до того, як корінь завершить гідратацію, React очистить наявний серверний HTML-вміст і перемкне весь корінь на клієнтський рендеринг.
root.unmount()
Викличте root.unmount
для знищення відрендереного дерева всередині кореня React.
root.unmount();
Застосунок, повністю побудований на React, зазвичай не має викликів до root.unmount
.
Це здебільшого корисно, якщо вузол DOM вашого кореня React (або будь-який з його предків) може бути видалений з DOM іншим кодом. Наприклад, уявіть собі панель вкладок jQuery, яка видаляє неактивні вкладки з DOM. Якщо вкладка буде видалена, все, що знаходиться всередині неї (включаючи корені React всередині), також буде видалено з DOM. У такому випадку вам потрібно сказати React, щоб він "припинив" керувати вмістом видаленого кореня, викликавши root.unmount
. Інакше компоненти всередині видаленого кореня не знатимуть, що потрібно очистити і звільнити глобальні ресурси, такі як підписки.
Виклик root.unmount
демонтує всі компоненти в корені та "від'єднає" React від кореневого DOM-вузла, включно з видаленням будь-яких обробників подій або станів у дереві.
Параметри
root.unmount
не приймає жодних параметрів.
Повернення
root.unmount
повертає undefined
.
Застереження
Виклик
root.unmount
демонтує всі компоненти у дереві та "від'єднає" React від кореневого DOM-вузла.Після виклику
root.unmount
неможливо повторно викликатиroot.render
у корені. Спроба викликатиroot.render
у не змонтованому корені призведе до помилки "Неможливо оновити не змонтований корінь".
Використання
Гідратація серверного HTML
Якщо HTML вашого застосунку було згенеровано react-dom/server
, вам потрібно гідратувати його на клієнтській стороні.
"]]" class="language-js">import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
Це призведе до гідратації серверного HTML всередині Вам не потрібно викликати Дерево React, якому ви передаєте Це важливо для зручності користування. Користувач витратить деякий час на перегляд згенерованого сервером HTML, перш ніж завантажиться ваш JavaScript-код. Серверний рендеринг створює ілюзію, що застосунок завантажується швидше, показуючи HTML-знімок його результатів. Раптовий показ іншого вмісту руйнує цю ілюзію. Ось чому результат рендерингу на сервері повинен відповідати початковому результату рендерингу на стороні клієнта. До найпоширеніших причин, що призводять до помилок гідратації, належать: React відновлюється після деяких помилок гідратації, але ви повинні виправити їх, як і інші вади. У кращому випадку вони призведуть до сповільнення, у гіршому - обробники подій можуть бути прив'язані до неправильних елементів. Застосунки, повністю побудовані з React, можуть рендерити весь документ як JSX, включаючи тег Щоб гідратувати весь документ, передайте Якщо атрибут або текстовий вміст окремого елемента неминуче відрізняється на сервері та клієнтській стороні (наприклад, мітка часу), ви можете вимкнути попередження про невідповідність гідратації. Щоб вимкнути попередження про гідратацію елемента, додайте Це працює лише на один рівень вглиб і призначено для аварійного виходу. Не зловживайте ним. Якщо це не текстовий вміст, React все одно не намагатиметься його виправити, тому він може залишатися неузгодженим до наступних оновлень. Якщо вам навмисно потрібно відрендерити щось різне на сервері та клієнтській стороні, ви можете зробити двопрохідний рендеринг. Компоненти, які рендеритимуть щось інше на клієнтській стороні, можуть читати змінну стану на кшталт Таким чином, початкова передача рендерингу відображатиме той самий вміст, що і сервер, уникаючи невідповідностей, але додаткова передача відбудеться синхронно одразу після гідратації. Такий підхід уповільнює гідратацію, оскільки компоненти доводиться рендерити двічі. Пам'ятайте про користувацький досвід при повільних з'єднаннях. Код JavaScript може завантажуватися значно пізніше, ніж початковий HTML-рендеринг, тому відображення іншого інтерфейсу одразу після гідратації може здатися користувачеві різким. Після завершення гідратації кореня ви можете викликати Якщо ви викликаєте Виклик import './styles.css';
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
);
import { useState } from 'react';
export default function App() {
return (
<>
<h1>Hello, world!</h1>
<Counter />
</>
);
}
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
You clicked me {count} times
</button>
);
}
hydrateRoot
знову або викликати його в інших місцях. З цього моменту React буде керувати DOM вашого застосунку. Для оновлення інтерфейсу користувача ваші компоненти будуть замість цього використовувати стан.hydrateRoot
, має видавати те саме виведення , що й на сервері.
typeof window !== 'undefined'
у логіці рендерингу.window.matchMedia
.
Гідратація всього документа
<html>
: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>
<Router />
</body>
</html>
);
}
document
глобально як перший аргумент до hydrateRoot
:import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document, <App />);
Придушення неминучих помилок невідповідності гідратації
suppressHydrationWarning={true}
:<!--
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>
import './styles.css';
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document.getElementById('root'), <App />);
export default function App() {
return (
<h1 suppressHydrationWarning={true}>
Current Date: {new Date().toLocaleDateString()}
</h1>
);
}
Робота з різним клієнтським та серверним вмістом
isClient
, яку ви можете встановити як true
в ефекті:<!--
HTML content inside <div id="root">...</div>
was generated from App by react-dom/server.
-->
<div id="root"><h1>Is Server</h1></div>
import './styles.css';
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document.getElementById('root'), <App />);
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>
);
}
Оновлення гідратованого кореневого компонента
root.render
для оновлення кореневого React-компонента. На відміну від createRoot
, вам зазвичай не потрібно цього робити, оскільки початковий вміст вже було відрендерено як HTML.root.render
в якийсь момент після гідратації, і структура дерева компонентів збігається з тим, що було відрендерено раніше, React збереже стан. Зверніть увагу, як ви можете вводити вхідні дані, що означає, що оновлення від повторюваних викликів
рендерингу щосекунди у цьому прикладі не є деструктивними:<!--
All HTML content inside <div id="root">...</div> was
generated by rendering <App /> with react-dom/server.
-->
<div id="root"><h1>Hello, world! <!-- -->0</h1><input placeholder="Type something here"/></div>
import { hydrateRoot } from 'react-dom/client';
import './styles.css';
import App from './App.js';
const root = hydrateRoot(
document.getElementById('root'),
<App counter={0} />
);
let i = 0;
setInterval(() => {
root.render(<App counter={i} />);
i++;
}, 1000);
export default function App({counter}) {
return (
<>
<h1>Hello, world! {counter}</h1>
<input placeholder="Type something here" />
</>
);
}
root.render
в гідратованому корені є рідкістю. Зазвичай замість цього ви оновлюєте стан всередині одного з компонентів.