Spec-Zone.ru › React

createRoot

createRoot позволяет создать корень для отображения компонентов React внутри узла DOM браузера.

const root = createRoot(domNode, options?)
  • Справочник
    • createRoot(domNode, options?)
    • root.render(reactNode)
    • root.unmount()
  • Использование
    • Отображение полностью построенного приложения с React
    • Отображение страницы, частично построенной с React
    • Обновление компонента корня
    • Показать диалог для непредвиденных ошибок
    • Отображение ошибок Error Boundary
    • Отображение диалога для восстанавливаемых ошибок
  • Отладка
    • Создал корень, но ничего не отображается
    • Ошибка: «Вы передали второй аргумент в root.render»
    • Ошибка: «Целевой контейнер не является элементом DOM»
    • Ошибка: «Функции не являются допустимыми как дочерние элементы React»
    • Мой серверно-отрендеренный HTML пересоздаётся с нуля

Справочник

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 Boundary. Вызывается с перехваченной error ошибкой Error Boundary и объектом errorInfo, содержащим componentStack.
    • необязательный onUncaughtError: Обратный вызов, вызываемый, когда ошибка выбрасывается и не перехватывается Error Boundary. Вызывается с 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.render, React очистит всё существующее содержимое HTML внутри корня React перед рендерингом компонента React в него.

  • Если узел DOM вашего корня содержит HTML, сгенерированный React на сервере или во время сборки, используйте hydrateRoot() вместо этого, который прикрепляет обработчики событий к существующему HTML.

  • Если вы вызываете render на том же корне более одного раза, React обновит DOM по мере необходимости, чтобы отразить последний переданный JSX. React решит, какие части DOM можно повторно использовать, а какие необходимо пересоздать, «сопоставив» его с ранее отрендеренным деревом. Вызов render на том же корне аналогичен вызову функции set компонента корня: React избегает ненужных обновлений DOM.


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 на размонтированном корне приведёт к ошибке «Нельзя обновить размонтированный корень». Однако вы можете создать новый корень для того же узла DOM после того, как предыдущий корень для этого узла был размонтирован.


Использование

Отображение полностью построенного приложения с React

Если ваше приложение полностью построено с React, создайте один корень для всего приложения.

import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'));
root.render(<App />);

Обычно этот код нужно выполнить один раз при запуске. Он:

  1. Найдёт узел DOM браузера, определённый в вашем HTML.
  2. Отобразит компонент 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 несколько раз. Обычно ваши компоненты будут обновлять состояние вместо этого.

Отображение диалогового окна для непредвиденных ошибок

По умолчанию React будет регистрировать все непредвиденные ошибки в консоли. Для реализации собственной системы отслеживания ошибок вы можете указать необязательный параметр onUncaughtError корневого элемента:

import { createRoot } from 'react-dom/client';

const root = createRoot(
  document.getElementById('root'),
  {
    onUncaughtError: (error, errorInfo) => {
      console.error(
        'Uncaught error',
        error,
        errorInfo.componentStack
      );
    }
  }
);
root.render(<App />);

Параметр onUncaughtError — это функция, которая вызывается с двумя аргументами:

  1. Ошибка error, которая была сгенерирована.
  2. Объект errorInfo, содержащий componentStack ошибки.

Вы можете использовать параметр onUncaughtError корневого элемента для отображения диалоговых окон об ошибках:

import { createRoot } from "react-dom/client";
import App from "./App.js";
import {reportUncaughtError} from "./reportError";
import "./styles.css";

const container = document.getElementById("root");
const root = createRoot(container, {
  onUncaughtError: (error, errorInfo) => {
    if (error.message !== 'Known error') {
      reportUncaughtError({
        error,
        componentStack: errorInfo.componentStack
      });
    }
  }
});
root.render(<App />);

Отображение ошибок границ ошибок

По умолчанию React будет регистрировать все ошибки, перехваченные границей ошибок, в console.error. Чтобы переопределить это поведение, вы можете указать необязательный параметр onCaughtError корневого элемента для обработки ошибок, перехваченных границей ошибок:

import { createRoot } from 'react-dom/client';

const root = createRoot(
  document.getElementById('root'),
  {
    onCaughtError: (error, errorInfo) => {
      console.error(
        'Caught error',
        error,
        errorInfo.componentStack
      );
    }
  }
);
root.render(<App />);

Параметр onCaughtError — это функция, которая вызывается с двумя аргументами:

  1. Ошибка error, перехваченная границей.
  2. Объект errorInfo, содержащий componentStack ошибки.

Вы можете использовать параметр onCaughtError корневого элемента для отображения диалоговых окон об ошибках или фильтрации известных ошибок из логов:

import { createRoot } from "react-dom/client";
import App from "./App.js";
import {reportCaughtError} from "./reportError";
import "./styles.css";

const container = document.getElementById("root");
const root = createRoot(container, {
  onCaughtError: (error, errorInfo) => {
    if (error.message !== 'Known error') {
      reportCaughtError({
        error, 
        componentStack: errorInfo.componentStack,
      });
    }
  }
});
root.render(<App />);

Отображение диалогового окна для исправимых ошибок

React может автоматически повторно отобразить компонент, чтобы попытаться восстановить ошибку, выброшенную в render. Если это успешно, React запишет исправимую ошибку в консоль, чтобы уведомить разработчика. Чтобы переопределить это поведение, вы можете указать необязательный параметр onRecoverableError корневого элемента:

import { createRoot } from 'react-dom/client';

const root = createRoot(
  document.getElementById('root'),
  {
    onRecoverableError: (error, errorInfo) => {
      console.error(
        'Recoverable error',
        error,
        error.cause,
        errorInfo.componentStack,
      );
    }
  }
);
root.render(<App />);

Параметр onRecoverableError — это функция, которая вызывается с двумя аргументами:

  1. Ошибка error, которую бросает React. Некоторые ошибки могут содержать исходную причину в виде error.cause.
  2. Объект errorInfo, содержащий componentStack ошибки.

Вы можете использовать параметр onRecoverableError корневого элемента для отображения диалоговых окон об ошибках:

import { createRoot } from "react-dom/client";
import App from "./App.js";
import {reportRecoverableError} from "./reportError";
import "./styles.css";

const container = document.getElementById("root");
const root = createRoot(container, {
  onRecoverableError: (error, errorInfo) => {
    reportRecoverableError({
      error,
      cause: error.cause,
      componentStack: errorInfo.componentStack,
    });
  }
});
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(...):

Консоль
Предупреждение: Вы передали второй аргумент в 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. Это произойдёт, если в документе в момент вызова нет узла с заданным идентификатором. Причин этому может быть несколько:

  1. Идентификатор, который вы ищете, может отличаться от идентификатора, используемого в файле HTML. Проверьте на наличие опечаток!
  2. Тег <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 удаляет весь этот HTML и затем заново создаёт все узлы 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API