# Rendering and reconciliation

> A state change re-runs your component; React diffs the result and touches only what changed.

Concept · Building apps · https://levelcode.org/concepts/react-rendering

In React, **rendering** means *calling your component function* to get a description of the UI. It's not the same thing as updating the DOM. The update has two phases:

1. **Render.** React calls the components that need updating. Each one returns JSX, which is a tree of plain objects.
2. **Commit.** React compares the new tree with the previous one (**reconciliation**) and applies only the differences to the real DOM.

Rendering is usually cheap. DOM changes are what's expensive, and reconciliation keeps them to a minimum.

## What triggers a render

- The component's **state changes** (`setState`, `useReducer` dispatch).
- Its **parent re-renders.** By default every child re-renders too, whether or not its props changed.
- A **context** it reads changes.

Props changing isn't a separate trigger. Props only change because a parent rendered. Each render sees a fresh snapshot of props and state, which is why a `setCount(count + 1)` called twice in one handler only adds 1. Use the updater form, `setCount((c) => c + 1)`, when the next value depends on the previous one.

## How the diff works

React assumes two things, which make the diff O(n) instead of O(n³):

- **A different element type means a different subtree.** If `<div>` becomes `<section>`, or `<Profile>` becomes `<Settings>`, React throws away the old subtree, **including all its state**, and builds a new one.
- **Keys identify children across renders.**

```jsx
{todos.map((todo) => <TodoItem key={todo.id} todo={todo} />)}
```

With stable keys, React can tell that an item moved instead of assuming every item after it changed. With array **indexes** as keys, inserting at the top shifts every key by one. Each item's state then sticks to the wrong row: a checked checkbox or a half-typed input jumps to its neighbour. Use an ID from the data.

Keys also work as a reset switch. `<Editor key={docId} />` remounts the editor with fresh state whenever the document changes.

## Before optimizing

- **Most re-renders don't matter.** Measure with the React DevTools Profiler before adding `memo`, `useMemo` or `useCallback`. The React Compiler can add those automatically.
- **Move state down** to the component that uses it, so fewer components re-render when it changes.
- **Don't store what you can compute.** Duplicated state and the effects that sync it are a more common source of bugs and wasted renders than slow components. See [derived state](https://levelcode.org/concepts/derived-state).
