createRoot を使うと、ブラウザの DOM ノード内に React コンポーネントを表示するためのルートを作成できます。

const root = createRoot(domNode, options?)

リファレンス

createRoot(domNode, options?)

createRoot を呼び出して、ブラウザの DOM 要素内にコンテンツを表示するための React ルートを作成します。

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 で完全に構築されたアプリは通常、ルートコンポーネントに対して 1 回だけ createRoot を呼び出します。ページのパーツに React の「振りかけ」を使用するページでは、必要に応じて個別のルートをいくつでも持つことができます。

以下の例で詳細をご覧ください。

パラメータ

  • domNode: DOM要素。 React は、この DOM 要素のルートを作成し、レンダリングされた React コンテンツを表示するために render などのルートで関数を呼び出すことができるようにします。

  • オプション options: この React ルートのオプションを持つオブジェクト。

    • オプション onCaughtError: React がエラー境界でエラーをキャッチしたときに呼び出されるコールバック。エラー境界でキャッチされた error と、componentStack を含む errorInfo オブジェクトとともに呼び出されます。
    • オプション onUncaughtError: エラーがスローされ、エラー境界でキャッチされなかった場合に呼び出されるコールバック。スローされた error と、componentStack を含む errorInfo オブジェクトとともに呼び出されます。
    • オプション onRecoverableError: React がエラーから自動的に回復したときに呼び出されるコールバック。 React がスローする error と、componentStack を含む errorInfo オブジェクトとともに呼び出されます。一部の回復可能なエラーには、error.cause として元のエラーの原因が含まれる場合があります。
    • オプション identifierPrefix: useId によって生成された ID に React が使用する文字列プレフィックス。同じページで複数のルートを使用する場合の競合を避けるのに役立ちます。

戻り値

createRoot は、2つのメソッドを持つオブジェクトを返します。それは renderunmount です。

注意点

  • アプリケーションがサーバーでレンダリングされている場合、createRoot() の使用はサポートされていません。代わりに hydrateRoot() を使用してください。
  • アプリケーション内で createRoot の呼び出しは通常1回だけです。フレームワークを使用している場合は、フレームワークがこの呼び出しを行っている場合があります。
  • コンポーネントの子ではない DOM ツリーの別の部分 (例えば、モーダルやツールチップ) に JSX をレンダリングしたい場合は、createRoot の代わりに createPortal を使用してください。

root.render(reactNode)

root.render を呼び出して、ReactルートのブラウザDOMノードにJSX ("Reactノード") を表示します。

root.render(<App />);

Reactは <App />root 内に表示し、その内部のDOMの管理を引き継ぎます。

以下の例で詳細をご覧ください。

パラメータ

  • reactNode: 表示したい *Reactノード*。これは通常、<App /> のようなJSXですが、createElement() で構築されたReact要素、文字列、数値、null、または undefined を渡すこともできます。

戻り値

root.renderundefined を返します。

注意点

  • root.render を最初に呼び出すと、ReactはReactルート内の既存のHTMLコンテンツをすべてクリアしてから、Reactコンポーネントをそこにレンダリングします。

  • ルートのDOMノードに、サーバー上またはビルド中にReactによって生成されたHTMLが含まれている場合は、代わりに既存のHTMLにイベントハンドラーをアタッチするhydrateRoot() を使用してください。

  • 同じルートで render を複数回呼び出すと、Reactは渡した最新のJSXを反映するために必要に応じてDOMを更新します。Reactは、DOMのどの部分を再利用できるか、どの部分を再作成する必要があるかを、以前にレンダリングされたツリーと「照合する」ことで判断します。同じルートで再度 render を呼び出すことは、ルートコンポーネントで set 関数 を呼び出すのと似ています。Reactは不要なDOMの更新を回避します。


root.unmount()

Reactルート内部でレンダリングされたツリーを破棄するには、root.unmount を呼び出します。

root.unmount();

Reactで完全に構築されたアプリには、通常、root.unmount の呼び出しはありません。

これは、ReactのルートのDOMノード(またはその祖先のいずれか)が、他のコードによってDOMから削除される可能性がある場合に特に役立ちます。たとえば、アクティブでないタブをDOMから削除するjQueryのタブパネルを想像してください。タブが削除されると、その内部にあるすべて(内部のReactルートを含む)もDOMから削除されます。その場合、Reactに削除されたルートのコンテンツの管理を「停止」するように指示する必要があります。これは、root.unmountを呼び出すことで行います。そうしないと、削除されたルート内のコンポーネントは、サブスクリプションなどのグローバルリソースをクリーンアップして解放する方法を知りません。

root.unmountを呼び出すと、ルート内のすべてのコンポーネントがアンマウントされ、ツリー内のすべてのイベントハンドラーや状態の削除を含め、ReactがルートのDOMノードから「分離」されます。

パラメーター

root.unmountはパラメーターを受け入れません。

戻り値

root.unmountundefinedを返します。

注意点

  • 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回だけ実行する必要があります。これにより、次の処理が行われます。

  1. HTMLで定義されているブラウザのDOMノードを検索します。
  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コンポーネントの内側にネストします。UIを更新する必要がある場合は、各コンポーネントがステートを使用してこれを行うことができます。DOMノードの外にモーダルやツールチップなどの追加コンテンツを表示する必要がある場合は、ポータルを使用してレンダリングします。

HTMLが空の場合、アプリのJavaScriptコードがロードされて実行されるまで、ユーザーには空白のページが表示されます。

<div id="root"></div>

これは非常に遅く感じる可能性があります!これを解決するには、コンポーネントから初期HTMLをサーバー上またはビルド中に生成できます。その後、訪問者はJavaScriptコードがロードされる前に、テキストを読んだり、画像を見たり、リンクをクリックしたりできます。この最適化をすぐに実行できるフレームワークの使用をお勧めします。実行されるタイミングによっては、これはサーバーサイドレンダリング(SSR)または静的サイト生成(SSG)と呼ばれます。

落とし穴

サーバーレンダリングまたは静的生成を使用するアプリは、createRootの代わりにhydrateRootを呼び出す必要があります。Reactは、HTMLからDOMノードを破棄して再作成する代わりにハイドレート(再利用)します。


Reactで部分的に構築されたページのレンダリング

ページが完全にReactで構築されていない場合、createRootを複数回呼び出して、Reactによって管理されるUIのトップレベルの各部分にルートを作成できます。root.renderを呼び出すことで、各ルートに異なるコンテンツを表示できます。

ここでは、index.htmlファイルで定義された2つのDOMノードに、2つの異なるReactコンポーネントがレンダリングされています。

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

また、document.createElement()で新しいDOMノードを作成し、それを手動でドキュメントに追加することもできます。

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オプションは、2つの引数で呼び出される関数です。

  1. スローされたエラー
  2. エラーのcomponentStackを含むerrorInfoオブジェクト。

エラーダイアログを表示するには、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オプションは、2つの引数で呼び出される関数です。

  1. バウンダリーによってキャッチされたエラー
  2. エラーのcomponentStackを含むerrorInfoオブジェクト。

エラーダイアログを表示したり、既知のエラーをログからフィルタリングしたりするには、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は、レンダリングでスローされたエラーから回復しようとして、コンポーネントを2回目に自動的にレンダリングすることがあります。成功した場合、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オプションは、2つの引数で呼び出される関数です。

  1. Reactがスローするエラー。一部のエラーには、error.causeとして元の原因が含まれる場合があります。
  2. エラーのcomponentStackを含むerrorInfoオブジェクト。

エラーダイアログを表示するには、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に2番目の引数を渡しました」

よくある間違いは、createRootのオプションをroot.render(...)に渡してしまうことです。

コンソール
警告: root.render(…)に2番目の引数を渡しましたが、1つの引数しか受け付けません。

修正するには、ルートオプションをroot.render(...)ではなく、createRoot(...)に渡してください。

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

たとえば、domNodenullの場合、getElementByIdnullを返したことを意味します。これは、呼び出し時にドキュメント内に指定されたIDを持つノードがない場合に発生します。それにはいくつかの理由が考えられます。

  1. 探しているIDが、HTMLファイルで使用したIDと異なる可能性があります。タイプミスがないか確認してください!
  2. バンドルの<script>タグは、HTML内でそのに表示されるDOMノードを「認識」できません。

このエラーが発生するもう1つの一般的な方法は、createRoot(domNode)の代わりにcreateRoot(<App />)と記述することです。


エラーが発生しています:「関数はReactの子として有効ではありません。」

このエラーは、root.renderに渡しているものがReactコンポーネントではないことを意味します。

これは、<Component />の代わりにComponentroot.renderを呼び出した場合に発生する可能性があります。

// 🚩 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が最初から再作成されます

アプリがサーバーレンダリングされており、Reactによって生成された初期HTMLが含まれている場合、ルートを作成してroot.renderを呼び出すと、そのHTMLがすべて削除され、DOMノードが最初から再作成されることに気づくかもしれません。これは、処理が遅くなり、フォーカスとスクロール位置がリセットされ、その他のユーザー入力が失われる可能性があります。

サーバーレンダリングされたアプリでは、createRootの代わりにhydrateRootを使用する必要があります。

import { hydrateRoot } from 'react-dom/client';
import App from './App.js';

hydrateRoot(
document.getElementById('root'),
<App />
);

APIが異なることに注意してください。特に、通常はこれ以上のroot.render呼び出しはありません。