hydrateRoot¶
hydrateRoot
позволяет отображать компоненты React внутри узла DOM браузера, HTML-содержимое которого было предварительно сгенерировано react-dom/server
.
1 |
|
Описание¶
hydrateRoot(domNode, reactNode, options?)
¶
Вызов hydrateRoot
для "прикрепления" React к существующему HTML, который уже был отрисован React в серверной среде.
1 2 3 4 |
|
React подключится к HTML, существующему внутри domNode
, и возьмет на себя управление DOM внутри него. Приложение, полностью построенное на React, обычно имеет только один вызов hydrateRoot
с корневым компонентом.
Параметры
domNode
: DOM-элемент, который был отображен как корневой элемент на сервере.reactNode
: "Узел React", используемый для рендеринга существующего HTML. Обычно это кусок JSX типа<App />
, который был отрисован с помощью методаReactDOM Server
, такого какrenderToPipeableStream(<App />)
.- опционально
options
: Объект с опциями для этого корня 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 браузера.
1 |
|
React обновит <App />
в гидратированном root
.
Параметры
reactNode
: "React-узел", который вы хотите обновить. Обычно это кусок JSX типа<App />
, но вы также можете передать элемент React, созданный с помощьюcreateElement()
, строку, число,null
илиundefined
.
Возвраты
root.render
возвращает undefined
.
Предупреждения
- Если вы вызовете
root.render
до того, как корень закончит гидрирование, React очистит существующий HTML-контент, отрендеренный сервером, и переключит весь корень на клиентский рендеринг.
root.unmount()
¶
Вызовите root.unmount
, чтобы уничтожить дерево рендеринга внутри корня React.
1 |
|
Приложение, полностью построенное на React, обычно не содержит вызовов root.unmount
.
Это в основном полезно, если DOM-узел вашего React root (или любой из его предков) может быть удален из DOM каким-либо другим кодом. Например, представьте себе панель вкладок jQuery, которая удаляет неактивные вкладки из DOM. Если вкладка будет удалена, все внутри нее (включая React roots внутри) также будет удалено из DOM. Вам нужно сказать React "перестать" управлять содержимым удаленного корня, вызвав root.unmount
. В противном случае компоненты внутри удаленного корня не очистятся и не освободят ресурсы, такие как подписки.
Вызов root.unmount
размонтирует все компоненты в корне и "отсоединит" React от корневого DOM-узла, включая удаление любых обработчиков событий или состояния в дереве.
Параметры
root.unmount
не принимает никаких параметров.
Возвраты
render
возвращает null
.
Ограничения
- Вызов
root.unmount
размонтирует все компоненты в дереве и "отсоединит" React от корневого DOM-узла. - После вызова
root.unmount
вы не сможете снова вызватьroot.render
на корне. Попытка вызватьroot.render
на немонтированном корне приведет к ошибке "Cannot update an unmounted root".
Использование¶
Гидрирование серверного HTML¶
Если HTML вашего приложения был сгенерирован react-dom/server
, вам нужно гидрировать его на клиенте.
1 2 3 |
|
Это приведет к гидратации HTML сервера внутри узла browser DOM с компонентом React для вашего приложения. Обычно вы делаете это один раз при запуске. Если вы используете фреймворк, он может сделать это за кадром для вас.
Чтобы гидратировать ваше приложение, React "прикрепляет" логику ваших компонентов к первоначально сгенерированному HTML с сервера. Гидратация превращает первоначальный снимок HTML с сервера в полностью интерактивное приложение, которое запускается в браузере.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Вам не придется вызывать hydrateRoot
снова или вызывать его в других местах. С этого момента React будет управлять DOM вашего приложения. Для обновления пользовательского интерфейса ваши компоненты будут использовать состояние.
Дерево React, которое вы передаете в hydrateRoot
, должно выдавать тот же результат, что и на сервере.
Это важно для пользовательского опыта. Пользователь потратит некоторое время на просмотр HTML, сгенерированного сервером, прежде чем загрузится ваш код JavaScript. Серверный рендеринг создает иллюзию того, что приложение загружается быстрее, показывая HTML-снимок его вывода. Внезапный показ другого содержимого разрушает эту иллюзию. Вот почему вывод серверного рендеринга должен совпадать с первоначальным выводом рендеринга на клиенте.
Наиболее распространенные причины, приводящие к ошибкам гидратации, включают:
- Лишние пробельные символы (например, новые строки) вокруг сгенерированного React HTML внутри корневого узла.
- Использование проверок типа
typeof window !== 'undefined'
в логике рендеринга. - Использование в логике рендеринга API, предназначенных только для браузера, таких как
window.matchMedia
. - Рендеринг разных данных на сервере и клиенте.
React восстанавливается после некоторых ошибок гидратации, но вы должны исправлять их, как и другие ошибки. В лучшем случае они приведут к замедлению работы; в худшем случае обработчики событий могут быть присоединены к неправильным элементам.
Гидрирование всего документа¶
Приложения, полностью построенные на React, могут рендерить весь документ как JSX, включая тег <html>
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Чтобы гидратировать весь документ, передайте глобальный document
в качестве первого аргумента в hydrateRoot
:
1 2 3 4 |
|
Подавление неизбежных ошибок несоответствия гидратации¶
Если атрибут или текстовое содержимое одного элемента неизбежно отличается на сервере и клиенте (например, метка времени), вы можете заглушить предупреждение о несоответствии гидратации.
Чтобы заглушить предупреждения о несоответствии гидратации для элемента, добавьте suppressHydrationWarning={true}
:
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 |
|
Он действует только на глубине одного уровня и предназначен для эвакуации. Не злоупотребляйте им. Если это не текстовое содержимое, React не будет пытаться исправить его, поэтому оно может оставаться непоследовательным до будущих обновлений.
Обработка различного содержимого клиента и сервера¶
Если вам намеренно нужно отобразить что-то разное на сервере и клиенте, вы можете сделать двухпроходной рендеринг. Компоненты, которые отображают что-то разное на клиенте, могут читать переменную состояния, например isClient
, которую вы можете установить в true
в Effect:
1 2 3 4 5 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
Таким образом, начальный проход рендеринга будет рендерить тот же контент, что и сервер, избегая несоответствий, но дополнительный проход будет происходить синхронно сразу после гидратации.
Такой подход делает процесс гидратации медленнее, поскольку ваши компоненты должны отображаться дважды. Помните о пользовательском опыте на медленных соединениях. Код JavaScript может загружаться значительно позже, чем первоначальный HTML-рендеринг, поэтому рендеринг другого пользовательского интерфейса сразу после гидратации также может показаться пользователю резким.
Обновление гидратированного корневого компонента¶
После завершения гидратации корня вы можете вызвать root.render
, чтобы обновить корневой React-компонент. В отличие от createRoot
, вам обычно не нужно этого делать, потому что исходное содержимое уже было отрендерено как HTML.
Если вы вызовете root.render
в какой-то момент после гидратации, и структура дерева компонентов совпадет с тем, что было отрисовано ранее, React сохранит состояние Обратите внимание, что вы можете вводить входные данные, что означает, что обновления от повторяющихся вызовов render
каждую секунду в этом примере не являются разрушительными:
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 7 8 |
|
Вызывать root.render
на гидратированном корне - редкость. Обычно вместо этого вы вызываете обновление состояния внутри одного из компонентов.
Источник — https://react.dev/reference/react-dom/client/hydrateRoot