Render, Commit, and Reconciliation in React

React turns state changes into screen changes in stages: it calculates a new UI tree, matches that tree with the previous one, and then updates the DOM.

One update, four useful questions

The words render and commit describe different work. Keeping them separate explains why a component can run without every DOM node being rebuilt.

  1. TriggerA first mount or a state update asks React for work.
  2. RenderReact calls components to calculate the next UI tree.
  3. ReconcileReact matches the new tree with the previous tree.
  4. CommitReact applies the required DOM changes.

After React commits, the browser can paint the result. Painting is browser work, not another React phase. On the first render there is no previous tree to match, so React creates the needed DOM. On later renders it can reuse matching parts.

Render calculates the next description

During rendering, React calls the component whose update was triggered and, when needed, the components below it. Each component reads its current props, state, and context, then returns JSX. JSX describes the desired result; it does not directly edit the page.

Changing name asks React to call Greeting again. The returned JSX describes the next heading.
import { useState } from "react";

function Greeting() {
  const [name, setName] = useState("Mira");

  return (
    <section>
      <h2>Hello, {name}!</h2>
      <button onClick={() => setName("Noah")}>
        Greet Noah
      </button>
    </section>
  );
}

Rendering must be pure. For the same inputs, a component should return the same JSX. Do not change the DOM, start a network request, or mutate an outside value while the component function runs. Event handlers and Effects provide places for those interactions.

Commit changes what exists

Once React has a completed result, it commits only the DOM operations needed to make the page match it. In the greeting example, React can keep the existing <section>, <h2>, and <button>, then replace only the heading's text.

React can reuse it

The element has a matching type and identity. React updates changed properties, attributes, event handlers, or text while leaving the rest in place.

React replaces it

The element's type or identity no longer matches. React removes the old DOM or component subtree and creates the new one.

A render does not guarantee a visible DOM change. If the calculated output is equivalent to what is already committed, React has nothing to mutate for that part of the page.

Reconciliation finds the difference

Reconciliation is React's matching process during rendering. React compares the new element tree with the previous one and decides which component instances and host elements can continue.

Same type
A <p> can continue as the same paragraph, and a <Profile> can continue as the same component instance. Changed props and children are processed.
Different type
Changing <p> to <div>, or <Profile> to <Settings>, replaces that part of the tree and resets state below it.
Stable key
Among siblings, a stable key helps React match an item even if its order changes. A changed key deliberately creates a different identity.
The outer <p> keeps the same type, so React reuses it and updates its class and text.
function SaveStatus({ isSaving }) {
  return (
    <p className={isSaving ? "saving" : "saved"}>
      {isSaving ? "Saving changes…" : "All changes saved"}
    </p>
  );
}

Reconciliation is why “render again” does not mean “rebuild the whole DOM.” Component output is recalculated first; DOM work follows from the differences React finds.

Batching groups triggers into one update

State setters queue updates. Batching lets React wait until the current interaction has finished, process related queued updates together, and usually produce one render and one commit for the batch. This avoids showing an intermediate screen such as a new selection with an old details panel.

Both state changes come from one click. React can calculate and commit the completed selection together.
function ContactPicker() {
  const [contactId, setContactId] = useState(1);
  const [isEditing, setIsEditing] = useState(true);

  function selectContact(nextId) {
    setContactId(nextId);
    setIsEditing(false);
  }

  return (
    <button onClick={() => selectContact(2)}>
      Open contact 2
    </button>
  );
}

Connection to state queues: batching changes when React processes related requests, not what each setter means. If several updates depend on pending state, functional updates are still required. React may also restart or repeat rendering before a commit, so component code must stay pure.

Component identity controls reuse

A component instance keeps its state when React can match the same component type in the same place under its parent, with the same key when one is present. This page focuses on identity as an input to reconciliation; the preserving-state notes use the same rule to explain what happens to state.

Stable keys let React match each TaskRow to the same task after sorting.
function TaskList({ tasks }) {
  const sortedTasks = [...tasks].sort((a, b) =>
    a.title.localeCompare(b.title)
  );

  return (
    <ul>
      {sortedTasks.map(task => (
        <TaskRow key={task.id} task={task} />
      ))}
    </ul>
  );
}
  • Keep component types stable. Define component functions at module scope, not inside another component's render.
  • Give changing lists stable keys. Use IDs from the data, not array positions or fresh random values.
  • Change a key intentionally. A new key tells reconciliation to replace that instance and reset its subtree.
  • Do not chase render counts. Write pure rendering logic and let React decide how to schedule safe work.

Keep this model: updates trigger work; rendering calculates; reconciliation matches identities; committing mutates the DOM. Batching lets related updates travel through that pipeline together.

Check your understanding

  1. If React renders a component, must it change the DOM?
    Show answer

    No. Rendering calculates the desired UI. If reconciliation finds that the committed DOM already matches, no DOM mutation is needed for that part.

  2. Why can two setter calls in one click lead to one completed screen update?
    Show answer

    React batches related updates from the interaction, processes their queues together, and can render and commit the completed result instead of committing each intermediate state.

  3. What lets a stateful list item keep its identity when the list is reordered?
    Show answer

    A stable key tied to the item's data lets reconciliation match that item with its previous component instance, even at a different sibling position.