In React, the element at one position in the tree is a <div> on one render and a <section> on the next, with identical children inside. What does React do with that node and everything beneath it?
answer
- React compares one thing first
- different type stops the comparison
- rebuild, not patch
- state lives with the instance, not the JSX
- identical children below do not help
basics
~20 sReact tears down the old subtree and builds a new one: DOM nodes are recreated, component state is lost, effect cleanups run and refs detach. Types must match at a position for React to update in place.
solid answer
~40 sReact compares the element `type` at each position before it compares anything else. A `div` and a `section` are different types, so React stops comparing there and replaces the whole subtree: it unmounts the old tree (running effect cleanups and `componentWillUnmount`, detaching refs, discarding all `useState` and `useReducer` values), removes the DOM node, then mounts the new tree from scratch. The identical children below do not save anything — replacing a parent replaces everything under it, because React never searches for reusable pieces across a type change. Had the type stayed `div` and only a prop changed, React would have kept the same DOM node and patched just the changed attributes, preserving all state below.
code
jsx · 5 linesexport function Panel({ wide, children }) {
return wide
? <section className="panel">{children}</section>
: <div className="panel">{children}</div>;
}go deeper
Be ready to state the rule plainly: same element type at a position means update in place, a different type means the old subtree is thrown away and a new one built, with state lost.
Explain the mechanics you can observe: which cleanups run, in what order the old tree unmounts before the new one mounts, and why a changed wrapper tag destroys state in children that did not change at all.
Show you can use the rule as a diagnostic. When state resets in production, trace which render changed the type or the structure at that position, and argue whether the fix is stabilising the tree or accepting the remount.
Frame it as an API-design constraint: component boundaries and conditional structure determine what survives an update, so a tree shape chosen carelessly builds state loss into the product. Set conventions that keep type-stable slots for stateful widgets.
## The comparison React makes first Every time a component renders, React produces a tree of plain element objects and walks it alongside the tree from the previous render, position by position. At each position the very first thing it compares is the element's `type`. For a host element the type is a string such as `'div'` or `'input'`; for a component it is a reference to the function (or class) itself. The outcome is binary: - **Types are equal** — React keeps the existing instance. For a host element that means the same DOM node stays in the document and only the props that actually changed are applied to it. For a component it means the same fiber, and therefore the same hook state, is reused; React calls the function again with the new props and recurses into what it returns. - **Types differ at all** — React stops comparing. It does not look inside to see whether anything is reusable. The old subtree is unmounted and a brand-new one is mounted in its place. ## What "the same position" means Position means the slot in the rendered tree: the same index under the same parent element. It is not the identity of the component function and not the line it was written on. Two elements written in different branches of a conditional can still land in the same position, and one element written on a single line can land in different positions on different renders. For a list of siblings, React matches by `key` rather than by index, which is a separate mechanism. ## What replacement actually costs A remount is not a repaint — it destroys everything the old tree was holding: - All `useState` / `useReducer` values in the subtree are discarded and re-initialised. - Every effect cleanup in the subtree runs, then the new tree's effects run as mounts. Subscriptions are torn down and re-established; timers restart. - Refs to the old DOM nodes are set to `null`; new nodes are created and refs re-attached. - The browser's own per-node state dies with the node: focus, text selection, scroll offset, the value of an uncontrolled input, the playback position of a `<video>`, an in-flight CSS transition, the document inside an `<iframe>`. - In legacy class components, `componentWillUnmount` runs on the old tree and `componentDidMount` on the new one. ## Why the check is total ```jsx // isWide flips -> the whole subtree below is thrown away return isWide ? <section className="panel"><Chat /></section> : <div className="panel"><Chat /></div>; ``` `Chat` is literally the same component in both branches, but it sits under a parent whose type changed, so it is unmounted with its parent and mounted fresh. React accepts this because the heuristic behind it holds most of the time: when the element type at a position changes, the developer usually meant something structurally different, and searching for salvageable fragments would cost more than rebuilding. ## The same rule for components ```jsx {mode === 'grid' ? <GridView items={items} /> : <ListView items={items} />} ``` `GridView` and `ListView` are different function references, so switching `mode` remounts. That is usually what you want — the two views have unrelated internal state. It becomes a bug when the two branches are really the *same* thing rendered slightly differently; then you keep one element and vary its props instead of swapping its type. ## The other side of the rule When the type is unchanged, the update is cheap and non-destructive. `<input className="a" />` becoming `<input className="b" />` sets one attribute on a node that never left the DOM, which is exactly why a controlled input does not lose focus while you type into it despite re-rendering on every keystroke. ## What to take away Type stability at a position is what preserves state. If a component's state resets unexpectedly, the first question is: what changed the element type or the tree structure at that position between the two renders?
- If the wrapper element's type stays the same and only its className changes, what happens to the children?Nothing destructive. React keeps the same DOM node, sets the one changed attribute on it, and recurses into the children to compare them by the same rules. Component state, refs, focus and scroll below the wrapper all survive, because no instance in the subtree was replaced.
- Does React compare the element types by value or by reference?Host elements are compared by their string type, so `'div'` matches `'div'`. Component elements are compared by the identity of the function or class itself, so two structurally identical component functions defined separately are different types and will not match.
- Is a remount ever the behaviour you want?Yes — when a position genuinely represents a different thing, remounting gives you a clean slate: fresh state, fresh subscriptions, no leftovers from the previous occupant. Switching between two unrelated views at the same slot is the normal case, and letting them remount is simpler and safer than trying to reconcile their state.
saying these in an interview costs you the question
- Thinks React diffs the real DOM against the new tree
- Says identical children are reused across a parent type change
- Believes state lives in the JSX, not in the mounted instance
- Assumes React finds the minimal set of DOM edits globally
- Claims a remount only recreates DOM, keeping hook state