Spec-Zone.ru › React 18

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-корня.

    • Только Canary необязательно onCaughtError: Обратный вызов, вызываемый, когда React ловит ошибку в Error Boundary. Вызывается с перехваченной error ошибкой Error Boundary и объектом errorInfo, содержащим componentStack.
    • Только Canary необязательно onUncaughtError: Обратный вызов, вызываемый, когда ошибка выбрасывается и не перехватывается Error Boundary. Вызывается с error ошибкой, которая была выброшена, и объектом errorInfo, содержащим componentStack.
    • необязательно onRecoverableError: Обратный вызов, вызываемый, когда React автоматически восстанавливается после ошибок. Вызывается с error ошибкой, выброшенной React, и объектом errorInfo, содержащим componentStack. Некоторые восстановимые ошибки могут содержать исходную причину ошибки как error.cause.
    • необязательно identifierPrefix: Префикс строки, который React использует для ID, сгенерированных 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 несколько раз не является обычной практикой. Обычно ваши компоненты будут обновлять состояние вместо этого.

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

Canary

onUncaughtError доступен только в последней версии React Canary.

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

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 root, чтобы отобразить диалоговое окно об ошибке:

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 />);

Отображение ошибок, перехваченных границей ошибок

Canary

onCaughtError доступен только в последней версии React Canary.

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

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 root для отображения диалоговых окон об ошибках или фильтрации известных ошибок из логов:

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 может автоматически повторно отобразить компонент, чтобы попытаться восстановиться от ошибки, сгенерированной в процессе отображения. Если попытка успешна, React запишет в консоль информацию о восстанавливаемой ошибке, чтобы уведомить разработчика. Чтобы изменить это поведение, вы можете предоставить необязательный параметр onRecoverableError root:

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 root для отображения диалоговых окон об ошибках:

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://18.react.dev/reference/react-dom/client/createRoot

Spec-Zone.ru

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