Engrain by ByteRush

RCT.02.01 Mid-level· 11 minCore — asked often

Reconciliation and keys: how React decides what to keep

React's diffing rules: a different type remounts, the same type updates, and list items are matched by key. See why index keys attach state to the wrong row, and how a key resets a component.

Comes up in: React, Recruiter screen

Learn#

Vivek’s to-do app has a note field on every row. When he deletes the first task, the next task shows the deleted task’s note. The data is right; the screen is wrong.

Reconciliation is how React turns a new render into DOM changes, by comparing new elements with the old ones (diffing). In lists, it matches items by key. With key={index}, removing the first item shifts every key, so React gives the old first row’s state to the new first item:

import { GlobalRegistrator } from "@happy-dom/global-registrator";
GlobalRegistrator.register(); // a DOM for Node; in a browser you already have one
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
const { createElement: h, useState, act } = await import("react");
const { createRoot } = await import("react-dom/client");

function Row({ label }) {
  const [draft] = useState(`draft for ${label}`); // state set once, on mount
  return h("li", null, `${label}: ${draft}`);
}
function List({ items, keyBy }) {
  return h("ul", null, items.map((label, i) => h(Row, { key: keyBy === "index" ? i : label, label })));
}
for (const keyBy of ["index", "id"]) {
  const box = document.createElement("div");
  const root = createRoot(box);
  await act(() => root.render(h(List, { items: ["Asha", "Ravi", "Meera"], keyBy })));
  await act(() => root.render(h(List, { items: ["Ravi", "Meera"], keyBy }))); // remove the first row
  console.log(`${keyBy} keys →`, [...box.querySelectorAll("li")].map((li) => li.textContent).join(" | "));
}
This example uses Node.js, so it runs in our checks rather than in your browser.

Output (verified)

index keys → Ravi: draft for Asha | Meera: draft for Ravi
id keys → Ravi: draft for Ravi | Meera: draft for Meera
Removing the first row with index keysStep 1 of 4

State

  • key 0: Asha (draft for Asha)
  • key 1: Ravi (draft for Ravi)
  • key 2: Meera (draft for Meera)

Before: three rows with index keys. Each Row keeps its own draft state.

Read the steps as text
  1. Before: three rows with index keys. Each Row keeps its own draft state.
  2. Asha is removed. The new list is Ravi, Meera, so their keys are now 0 and 1.
  3. React matches by key: key 0 still exists, so it updates the old Asha row with label Ravi, keeping Asha's state.
  4. With id keys, Asha's row is removed and the others keep their own state.

Predict#

Predict first

A component renders <input> when editing and <textarea> otherwise, at the same place. What happens to typed text when it switches?

Interview angle#

Say it like this — about 30 seconds

“Reconciliation compares the new element tree with the previous one using simple rules. If the type at a position changes, React unmounts the old subtree and mounts a new one. If the type is the same, it keeps the instance and updates its props. In lists, children are matched by key, so keys must be stable and unique among siblings. Index keys break when items are inserted, removed or reordered: state and DOM attach to the wrong item. Changing a key forces a reset.”

Stays on your device. Nothing is uploaded.
Follow-up How does React's reconciliation algorithm work?
It walks the trees by position: different type means remount, same type means update props, and list children are matched by key, giving roughly linear work.
Follow-up Why are keys important, and what goes wrong with array indexes?
Keys give list items identity. With indexes, a removal or reorder shifts identities, so state, focus and input values stick to the wrong rows.
Follow-up How would you force a component to reset its state?
Give it a new key, such as <Profile key={userId} />: React mounts a fresh instance.

Practice#

Guided

Implement React’s matching rules for one level of children.

Done when

  • Same key and same type is an update; anything else is a mount.
  • Missing keys fall back to the index.
  • Old children that are not updated are listed for unmounting, in their old order.
Your solution
Ctrl/⌘ + Enter

Remember#

Try to answer each card before you open it. Then add them to your reviews.

What does React do when the element type at a position changes?

Unmounts the old subtree and mounts a new one; state is lost.

Why are index keys risky?

Inserts, removals and reorders shift keys, so state attaches to the wrong item.

How do you reset a component's state on purpose?

Change its key.

Must keys be unique across the whole app?

No, only among siblings in the same list.

Go deeper

Four layers. Stop at the one your interview needs; each ends with a quick check.

The core ideaEvery round
Two rules make diffing fast: elements of different types produce different trees, and keys mark which children are stable. Use ids from your data as keys; index keys are fine only for static lists Source: React: Keeping list items in order with key.
Check yourself: When are index keys acceptable?

When the list never reorders, filters or has items inserted or removed, and rows have no state.

How it works underneathSenior rounds
React ties state to a position in the tree plus the type there. A component defined inside another is a new function each render, a new type, so it remounts every time Source: React: Preserving and resetting state.
Check yourself: Why does a component defined inside another lose its state each render?

A new function is created each render, so its type changes and React remounts it.

Edge cases and trapsWhere people slip
Changing a key remounts, even with the same type. That is the cleanest way to reset a form when the selected record changes, instead of an effect that copies props into state.
Check yourself: Does a key change in the same position remount even with the same type?

Yes. A new key is a new identity.

In productionStaff-level answers

Keep keys stable across renders: never generate them during render. For lists without ids, create ids when the data is created or loaded. Big lists also need virtualization (RCT.11.02).

Check yourself: What does React warn about in development for lists?

Missing keys and duplicate keys among siblings.

Finished the five steps? Mark it, and its cards join your reviews.

Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.

Interview questions this answers

  • How does React's reconciliation algorithm work?
  • Why are keys important? What goes wrong with array indexes as keys?
  • How would you force a component to reset its state?