Capítulo 22 de 116

Chapter 22: Render and Commit

Core Idea

Every screen update goes through three distinct steps — trigger, render, commit — and understanding them explains why rendering (React calling your components) doesn't automatically mean the DOM changes.

Key Concepts

  • Step 1 — Trigger: a render happens for exactly two reasons — the component's initial render (createRoot(node).render(<App />)), or a state update (calling a useState setter) on that component or an ancestor.
  • Step 2 — Render: "rendering" literally means React calling your component functions to figure out what should be on screen. On initial render, React calls the root component; on a re-render, it calls the component whose state changed. This is recursive — if a called component returns another component, React calls that one next, and so on, until there's nothing left to resolve.
  • Rendering must be pure (see Ch 18): same inputs → same JSX, no mutating anything that predates the call. Strict Mode's double-invoke-in-dev behavior exists specifically to surface violations of this.
  • Step 3 — Commit: only after all rendering resolves does React touch the DOM. On initial render it uses appendChild()-style APIs to place everything; on a re-render, it applies only the minimal diff calculated during the render step — React only changes DOM nodes where the render output actually differs from last time.
  • Concrete proof of the diffing: a <Clock> component re-rendering every second (new time prop) alongside an <input> the user is typing into — the <input>'s typed text survives every re-render because React sees the <input> element is in the same JSX position and leaves its DOM node (and thus its live value) untouched, updating only the <h1> text.
  • Browser paint is a separate, later step: after React commits to the DOM, the browser repaints the screen — that's a browser-level step outside React's control, referred to as "painting" in the docs to avoid confusing it with React's own "rendering."

Key Takeaways

  1. "Render" and "commit" are not the same thing — a component can be called (rendered) without any DOM node actually changing, if its output is identical to last time.
  2. The <input>-keeps-its-text-during-unrelated-re-renders behavior isn't magic — it's a direct consequence of React only touching DOM nodes whose calculated output differs, combined with element-position matching.
  3. Rendering all the way down from an updated component is the default and usually fine; treat it as a performance concern only after profiling shows it's actually slow (don't optimize prematurely).

Connects To

  • Ch 18 (Keeping Components Pure): the purity requirement this chapter's "render" step depends on.
  • Ch 21 (State: A Component's Memory): what actually triggers a re-render in the first place.
  • Ch 30 (Preserving and Resetting State): the deeper rules behind "same position in JSX = same DOM node preserved."