Frontend Engineering
React Fiber and Reconciliation
Quiz: Reconciliation — What Updates?
advanced12 min read
Test Your Reconciliation Knowledge
You've been through fiber architecture, the diffing algorithm, keys, and the render/commit phases. Time to put it all together and see if you really get it. For each scenario, predict exactly what React does to the DOM.
Fair warning: these target the most common misunderstandings about reconciliation. If you get them all right on the first try, you understand React's internals better than most senior engineers.
Scenario 1: Type Change at Root
function App({ isAdmin }) {
if (isAdmin) {
return (
<section>
<Counter />
<UserInfo />
</section>
);
}
return (
<div>
<Counter />
<UserInfo />
</div>
);
}
// Counter has internal state: count = 5
// isAdmin changes from true to false
Quiz
Scenario 2: Same Type, Different Props
function App({ theme }) {
return (
<div className={`app ${theme}`}>
<h1 style={{ color: theme === 'dark' ? 'white' : 'black' }}>
Welcome
</h1>
<Counter />
</div>
);
}
// theme changes from 'light' to 'dark'
Quiz
Scenario 3: Conditional Rendering and Position
function App({ showBanner }) {
return (
<div>
{showBanner && <Banner />}
<Counter />
<Footer />
</div>
);
}
// Counter has count = 10. showBanner changes from false to true.
Quiz
Scenario 4: List Reordering Without Keys
function App() {
const [reversed, setReversed] = useState(false);
const items = reversed
? ['Charlie', 'Bob', 'Alice']
: ['Alice', 'Bob', 'Charlie'];
return (
<ul>
{items.map(name => (
<li>{name} <input defaultValue="" /></li>
))}
</ul>
);
}
// User types "hello" in Alice's input. Then clicks reverse.
Quiz
Scenario 5: Key-Based Reordering
function App() {
const [reversed, setReversed] = useState(false);
const items = reversed
? [{ id: 3, name: 'Charlie' }, { id: 2, name: 'Bob' }, { id: 1, name: 'Alice' }]
: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }];
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name} <input defaultValue="" /></li>
))}
</ul>
);
}
// User types "hello" in Alice's input (id=1). Then clicks reverse.
Quiz
Scenario 6: Component Identity Change
function App({ mode }) {
const Editor = mode === 'code' ? CodeEditor : TextEditor;
return (
<div>
<Editor content="Hello world" />
</div>
);
}
// CodeEditor and TextEditor are different components.
// User is editing in CodeEditor. mode changes to 'text'.
Quiz
Scenario 7: Fragment Children
function App({ count }) {
return (
<div>
{count > 0 ? (
<>
<Badge count={count} />
<Counter />
</>
) : (
<Counter />
)}
</div>
);
}
// Counter has count = 7. count prop changes from 3 to 0.
Quiz
Scenario 8: Key Reset Pattern
function App() {
const [selectedUserId, setSelectedUserId] = useState(1);
return (
<div>
<UserSelector onSelect={setSelectedUserId} />
<UserProfile key={selectedUserId} userId={selectedUserId} />
</div>
);
}
function UserProfile({ userId }) {
const [editing, setEditing] = useState(false);
const [draft, setDraft] = useState('');
return (
<div>
<h1>User {userId}</h1>
{editing ? (
<textarea value={draft} onChange={e => setDraft(e.target.value)} />
) : (
<button onClick={() => setEditing(true)}>Edit</button>
)}
</div>
);
}
// User is editing User 1 with draft = "Hello". Selects User 2.
Quiz
Key Takeaways
Key Rules
- 1Wrapper type changes (div → section) destroy the ENTIRE subtree — all child state is lost.
- 2Same type at same position = state preserved. Parent re-renders still trigger child re-renders, but state survives.
- 3Without keys, list items match by position. DOM state (input values, scroll position) stays at the position, not with the data.
- 4With keys, list items match by identity. DOM nodes move with their keys, preserving both React state and DOM state.
- 5Component type comparison is by reference (===). Different functions = different types = full remount.
- 6Fragments affect tree structure. Adding/removing elements around a component changes its position, potentially resetting state.
- 7Key changes on non-list elements force a clean remount — the 'key as reset' pattern for resetting component state.
- 8React.memo prevents re-rendering when props haven't changed, but it doesn't affect reconciliation or state preservation.