React · Topic 1 of 8

Rendering and reconciliation

Card 1 of 11

What you will learn

Every update runs in two phases: a pure render that computes what the UI should look like, and a commit that applies it to the DOM. Reconciliation decides, by element type, position, and key, which existing instances to keep and which to reset.

Render vs commit

Render means React calls your components to get a tree of elements. It must be pure, and React may run it more than once, pause it, or throw it away.

Commit is the part that touches the DOM, attaches refs, and runs layout effects. It is synchronous. Passive effects from useEffect usually follow after paint.

Elements are just objects

JSX creates plain objects with a type, props, and key. They describe the UI and cost almost nothing to create. React compares the new tree of descriptions with the previous one to decide what to change.

If an element has the exact same reference as last time, React can skip that subtree entirely.

Identity is type plus position

At each position, same type means update the existing instance and keep its state. Different type means tear down the subtree and mount a new one.

This is why defining a component inside another component remounts it every render: its type is a new function each time.

Example

Identity is type plus position

function Parent() {
  // BAD: new type every render
  const Row = () => <input />;
  return <Row />;
}

Keys control identity in lists

Within siblings, keys match items across renders so state moves with the data. Use stable ids, not indexes, when lists can reorder, insert, or delete.

Keys also work outside lists. Changing a key forces a fresh instance, which is the cleanest way to reset state.

Example

Keys control identity in lists

<Profile key={userId} userId={userId} />

Batching and priority

React batches all updates from the same tick into one render, whether they come from events, timeouts, or promises. State is a snapshot, so setN(n + 1) three times still adds one.

startTransition and useDeferredValue mark work as low priority and interruptible, so urgent input renders first. Use flushSync only when you must read the DOM right away.

Key points

  • Render is pure and can be repeated or discarded; commit mutates the DOM.
  • Children re-render with their parent unless bailed out via memo or an identical element reference.
  • Same type at the same position keeps state; a different type resets it.
  • Use stable unique keys; change a key to deliberately reset a subtree.
  • Updates are batched automatically, and state inside a render is a snapshot.

Common mistakes

  • Declaring components inside other components, which remounts them on every render.
  • Using array index as key in lists that reorder or change.
  • Mutating variables, refs, or the DOM during render.
  • Passing inline objects or functions to memo components and expecting memo to help.
  • Assuming state updates apply immediately instead of on the next render.

Lesson complete

Ready to check what you learned?

Swipe left or right, or use the buttons.