createRoot
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つのメソッドを持つオブジェクトを返します。それは render
と unmount
です。
注意点
- アプリケーションがサーバーでレンダリングされている場合、
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.render
は undefined
を返します。
注意点
-
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.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回だけ実行する必要があります。これにより、次の処理が行われます。
- HTMLで定義されているブラウザのDOMノードを検索します。
- アプリの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ノードの外にモーダルやツールチップなどの追加コンテンツを表示する必要がある場合は、ポータルを使用してレンダリングします。
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つの引数で呼び出される関数です。
- スローされたエラー。
- エラーの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つの引数で呼び出される関数です。
- バウンダリーによってキャッチされたエラー。
- エラーの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つの引数で呼び出される関数です。
- Reactがスローするエラー。一部のエラーには、error.causeとして元の原因が含まれる場合があります。
- エラーの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(...)
ではなく、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 />);
たとえば、domNode
がnull
の場合、getElementById
がnull
を返したことを意味します。これは、呼び出し時にドキュメント内に指定されたIDを持つノードがない場合に発生します。それにはいくつかの理由が考えられます。
- 探しているIDが、HTMLファイルで使用したIDと異なる可能性があります。タイプミスがないか確認してください!
- バンドルの
<script>
タグは、HTML内でその後に表示されるDOMノードを「認識」できません。
このエラーが発生するもう1つの一般的な方法は、createRoot(domNode)
の代わりにcreateRoot(<App />)
と記述することです。
エラーが発生しています:「関数はReactの子として有効ではありません。」
このエラーは、root.render
に渡しているものがReactコンポーネントではないことを意味します。
これは、<Component />
の代わりにComponent
でroot.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
呼び出しはありません。