createRoot
createRoot позволяет создать корень для отображения компонентов React внутри узла DOM браузера.
const root = createRoot(domNode, options?)
Справочник
createRoot(domNode, options?)
Вызовите createRoot, чтобы создать корень React для отображения содержимого внутри элемента DOM браузера.
import { createRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = createRoot(domNode); React создаст корень для domNode и возьмёт на себя управление DOM внутри него. После создания корня вызовите root.render, чтобы отобразить в нём компонент React:
root.render(<App />); У приложения, полностью созданного с помощью React, обычно будет только один вызов createRoot для корневого компонента. На странице, где React используется лишь для отдельных фрагментов, может быть столько отдельных корней, сколько потребуется.
Параметры
-
domNode: DOM-элемент. React создаст корень для этого DOM-элемента и позволит вызывать методы корня, напримерrender, чтобы отображать содержимое React. -
необязательно
options: объект с параметрами этого корня React.-
необязательно
onCaughtError: функция обратного вызова, вызываемая, когда React перехватывает ошибку в границе ошибок. Вызывается сerror, перехваченной границей ошибок, и объектомerrorInfo, содержащимcomponentStack. -
необязательно
onUncaughtError: функция обратного вызова, вызываемая, когда возникает ошибка, не перехваченная границей ошибок. Вызывается сerror, которое было выброшено, и объектомerrorInfo, содержащимcomponentStack. -
необязательно
onRecoverableError: функция обратного вызова, вызываемая, когда React автоматически восстанавливается после ошибок. Вызывается с объектомerror, который выбрасывает React, и объектомerrorInfo, содержащимcomponentStack. Некоторые ошибки, допускающие восстановление, могут содержать исходную причину ошибки вerror.cause. -
необязательно
identifierPrefix: строковый префикс, который React использует для идентификаторов, создаваемых с помощьюuseId. Полезен для предотвращения конфликтов при использовании нескольких корней на одной странице.
-
необязательно
Возвращаемое значение
createRoot возвращает объект с двумя методами: render и unmount.
Предупреждения
- Если ваше приложение отображается на сервере, использовать
createRoot()нельзя. Вместо этого используйтеhydrateRoot(). - Скорее всего, в приложении будет только один вызов
createRoot. Если вы используете фреймворк, он может выполнить этот вызов за вас. - Если нужно отобразить фрагмент JSX в другой части дерева DOM, которая не является дочерним элементом вашего компонента (например, модальное окно или всплывающую подсказку), используйте
createPortal, а неcreateRoot.
root.render(reactNode)
Вызовите root.render, чтобы отобразить фрагмент JSX («узел React») в узле DOM браузера, принадлежащем корню React.
root.render(<App />); React отобразит <App /> в root и возьмёт на себя управление DOM внутри него.
Параметры
-
reactNode: узел React, который нужно отобразить. Обычно это фрагмент JSX, например<App />, но можно также передать элемент React, созданный с помощьюcreateElement(), строку, число,nullилиundefined.
Возвращаемое значение
root.render возвращает undefined.
Предупреждения
-
При первом вызове
root.renderReact удалит всё существующее HTML-содержимое внутри корня React, прежде чем отобразить в нём компонент React. -
Если узел DOM корня содержит HTML, созданный React на сервере или во время сборки, используйте вместо этого
hydrateRoot(), который добавляет обработчики событий к существующей HTML-разметке. -
Если вызвать
renderдля одного и того же корня несколько раз, React обновит DOM так, чтобы он соответствовал последнему переданному JSX. React определит, какие части DOM можно повторно использовать, а какие необходимо создать заново, «сопоставив их» с ранее отображённым деревом. Повторный вызовrenderдля того же корня аналогичен вызову функцииsetдля корневого компонента: React избегает ненужных обновлений DOM. -
Хотя после начала отрисовка выполняется синхронно,
root.render(...)— нет. Это означает, что код послеroot.render()может выполниться до запуска эффектов (useLayoutEffect,useEffect), относящихся к конкретной отрисовке. Обычно это не проблема и редко требует изменений. В редких случаях, когда важен момент запуска эффектов, можно обернутьroot.render(...)вflushSync, чтобы гарантировать, что первоначальная отрисовка полностью выполнится синхронно.const root = createRoot(document.getElementById('root')); root.render(<App />); // 🚩 The HTML will not include the rendered <App /> yet: console.log(document.body.innerHTML);
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для размонтированного корня приведёт к ошибке «Cannot update an unmounted root». Однако после размонтирования предыдущего корня для этого узла DOM можно создать новый корень.
Использование
Отображение приложения, полностью созданного с помощью React
Если ваше приложение полностью создано с помощью React, создайте один корень для всего приложения.
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />); Обычно этот код нужно выполнить только один раз при запуске. Он выполнит следующие действия:
- Найдёт узел DOM браузера, указанный в HTML.
- Отобразит внутри него компонент React вашего приложения.
import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; const root = createRoot(document.getElementById('root')); root.render(<App />);
Если ваше приложение полностью создано с помощью React, вам не нужно создавать дополнительные корни или повторно вызывать root.render.
С этого момента React будет управлять DOM всего приложения. Чтобы добавить компоненты, вложите их в компонент App. Чтобы обновить пользовательский интерфейс, каждый компонент может сделать это с помощью состояния. Если нужно отобразить дополнительное содержимое, например модальное окно или всплывающую подсказку, за пределами узла DOM, отрисуйте его с помощью портала.
Примечание
Если HTML пуст, пользователь увидит пустую страницу, пока не загрузится и не выполнится JavaScript-код приложения:
<div id="root"></div>
Это может показаться очень медленным! Чтобы решить эту проблему, можно сгенерировать исходный HTML из компонентов на сервере или во время сборки. Тогда посетители смогут читать текст, просматривать изображения и переходить по ссылкам ещё до загрузки JavaScript-кода. Мы рекомендуем использовать фреймворк, который выполняет эту оптимизацию из коробки. В зависимости от времени выполнения это называется рендерингом на стороне сервера (SSR) или генерацией статического сайта (SSG).
Важно
Приложения, использующие серверный рендеринг или статическую генерацию, должны вызывать hydrateRoot, а не createRoot. В этом случае React будет гидратировать (повторно использовать) узлы DOM из HTML, а не удалять и создавать их заново.
Отображение страницы, частично созданной с помощью React
Если ваша страница создана не полностью с помощью React, можно несколько раз вызвать createRoot, чтобы создать корень для каждого верхнеуровневого фрагмента пользовательского интерфейса, которым управляет React. Вызвав root.render, вы сможете отображать в каждом корне разное содержимое.
В этом примере два разных компонента React отображаются в двух узлах DOM, заданных в файле index.html:
import './styles.css'; import { createRoot } from 'react-dom/client'; import { Comments, Navigation } from './Components.js'; const navDomNode = document.getElementById('navigation'); const navRoot = createRoot(navDomNode); navRoot.render(<Navigation />); const commentDomNode = document.getElementById('comments'); const commentRoot = createRoot(commentDomNode); commentRoot.render(<Comments />);
Также можно создать новый узел DOM с помощью document.createElement() и вручную добавить его в документ.
const domNode = document.createElement('div');
const root = createRoot(domNode);
root.render(<Comment />);
document.body.appendChild(domNode); // You can add it anywhere in the document Чтобы удалить дерево React из узла DOM и очистить все используемые им ресурсы, вызовите root.unmount.
root.unmount(); Это нужно в основном в случаях, когда ваши компоненты React находятся внутри приложения, написанного на другом фреймворке.
Обновление корневого компонента
Можно несколько раз вызвать render для одного и того же корня. Если структура дерева компонентов совпадает с ранее отрисованной, React сохранит состояние. Обратите внимание, что в поле ввода можно печатать: это означает, что обновления, выполняемые в этом примере каждую секунду повторными вызовами render, не приводят к сбросу содержимого:
import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; const root = createRoot(document.getElementById('root')); let i = 0; setInterval(() => { root.render(<App counter={i} />); i++; }, 1000);
Несколько вызовов render — редкость. Обычно компоненты вместо этого обновляют состояние.
Регистрация ошибок в production-среде
По умолчанию React записывает все ошибки в консоль. Чтобы реализовать собственную систему отчётов об ошибках, можно передать необязательные обработчики ошибок в параметры корня: onUncaughtError, onCaughtError и onRecoverableError:
import { createRoot } from "react-dom/client";
import { reportCaughtError } from "./reportError";
const container = document.getElementById("root");
const root = createRoot(container, {
onCaughtError: (error, errorInfo) => {
if (error.message !== "Known error") {
reportCaughtError({
error,
componentStack: errorInfo.componentStack,
});
}
},
}); Параметр onCaughtError — это функция, вызываемая с двумя аргументами:
- ошибка, которая была выброшена.
- Объект errorInfo, содержащий componentStack ошибки.
Совместно с onUncaughtError и onRecoverableError эти параметры позволяют реализовать собственную систему отчётов об ошибках:
import { createRoot } from "react-dom/client"; import App from "./App.js"; import { onCaughtErrorProd, onRecoverableErrorProd, onUncaughtErrorProd, } from "./reportError"; const container = document.getElementById("root"); const root = createRoot(container, { // Keep in mind to remove these options in development to leverage // React's default handlers or implement your own overlay for development. // The handlers are only specfied unconditionally here for demonstration purposes. onCaughtError: onCaughtErrorProd, onRecoverableError: onRecoverableErrorProd, onUncaughtError: onUncaughtErrorProd, }); root.render(<App />);
Устранение неполадок
Я создал корень, но ничего не отображается
Убедитесь, что вы не забыли действительно отрисовать приложение в корне:
import { createRoot } from 'react-dom/client';
import App from './App.js';
const root = createRoot(document.getElementById('root'));
root.render(<App />); Пока вы этого не сделаете, ничего не будет отображаться.
Появляется ошибка: «Вы передали второй аргумент в root.render»
Распространённая ошибка — передавать параметры для createRoot в root.render(...):
Чтобы исправить это, передавайте параметры корня в createRoot(...), а не в root.render(...):
// 🚩 Wrong: root.render only takes one argument.
root.render(App, {onUncaughtError});
// ✅ Correct: pass options to createRoot.
const root = createRoot(container, {onUncaughtError});
root.render(<App />); Появляется ошибка: «Целевой контейнер не является элементом DOM»
Эта ошибка означает, что переданное в createRoot значение не является узлом DOM.
Если вы не уверены, что происходит, попробуйте вывести его в консоль:
const domNode = document.getElementById('root');
console.log(domNode); // ???
const root = createRoot(domNode);
root.render(<App />); Например, если domNode — это null, значит, getElementById вернул null. Такое произойдёт, если в момент вызова в документе нет узла с указанным ID. Причин может быть несколько:
- ID, который вы ищете, может отличаться от ID, указанного в HTML-файле. Проверьте, нет ли опечаток!
- Тег
<script>в вашем пакете не может «видеть» узлы DOM, расположенные в HTML после него.
Ещё одна распространённая причина этой ошибки — запись createRoot(<App />) вместо createRoot(domNode).
Появляется ошибка: «Функции не являются допустимыми дочерними элементами React»
Эта ошибка означает, что переданное в root.render значение не является компонентом React.
Это может произойти, если вызвать root.render с Component вместо <Component />:
// 🚩 Wrong: App is a function, not a Component.
root.render(App);
// ✅ Correct: <App /> is a component.
root.render(<App />); Или если передать функцию в root.render, а не результат её вызова:
// 🚩 Wrong: createApp is a function, not a component.
root.render(createApp);
// ✅ Correct: call createApp to return a component.
root.render(createApp()); Моя HTML-разметка, отрисованная на сервере, создаётся заново с нуля
Если ваше приложение отрисовывается на сервере и содержит исходную HTML-разметку, созданную React, вы можете заметить, что создание корня и вызов root.render удаляют всю эту разметку, а затем заново создают все узлы DOM. Это может быть медленнее, сбрасывает фокус и положение прокрутки, а также может привести к потере других пользовательских данных.
В приложениях с серверной отрисовкой необходимо использовать hydrateRoot вместо createRoot:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
); Обратите внимание, что его API отличается. В частности, обычно больше не нужно вызывать root.render.
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/reference/react-dom/client/createRoot