Capítulo 94 de 116

Chapter 94: createRoot

Core Idea

createRoot(domNode, options?) creates a React root attached to a browser DOM node — calling .render(<App />) on that root is what actually starts (and later updates) a client-rendered React tree, the mechanism first introduced in Ch 22.

Key Concepts

  • Signature: const root = createRoot(domNode, options?), then root.render(<App />). domNode must be an empty container (or one whose contents React should fully take over/replace) — this is not the hydration path (Ch 95) for pre-rendered server HTML.
  • Called once per root, typically at the entry point — most apps call createRoot exactly once (on the top-level container, e.g. #root), though multiple independent roots on one page are supported (each with its own identifierPrefix option to avoid useId collisions, Ch 55).
  • root.render() can be called again to update what's displayed — but re-rendering via state updates (Ch 21) inside the already-rendered tree is the normal way updates happen; calling root.render() directly again is mainly for the very unusual case of swapping out the entire top-level tree.
  • root.unmount() destroys the tree, running cleanup for every component and Effect within it — used when a page has multiple independently mountable React roots and one needs to be torn down without a full page reload.
  • Options: includes identifierPrefix (namespacing useId values across multiple roots) and onUncaughtError/onCaughtError/onRecoverableError callbacks for custom error-reporting integration at the root level.

Code Examples

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

const root = createRoot(document.getElementById('root'));
root.render(<App />);
  • What it demonstrates: the standard client-app bootstrap — the entire app tree attaches to one empty container element.

Key Takeaways

  1. domNode for createRoot should be empty — using it on a container with existing server-rendered markup you want to preserve is the wrong tool; that's hydrateRoot.
  2. This is almost always called exactly once, in the app's entry-point file — application logic updates the UI via state, not by calling root.render() repeatedly.
  3. root.unmount() is the explicit teardown path for multi-root pages, running the same cleanup guarantees as any component/Effect unmount elsewhere in React.

Connects To

  • Ch 5 (Add React to an Existing Project): the partial-page-integration use case this API underlies.
  • Ch 95 (hydrateRoot): the alternative for taking over server-rendered HTML instead of an empty container.
  • Ch 55 (useId): why identifierPrefix matters on pages with multiple roots.