When a list re-renders — rows reordered, one removed, one inserted — a framework must transform the old DOM into the new one without blowing away and rebuilding every node. Blowing them away loses focus, scroll, input values, and animation state, and it's slow. The fix is keyed reconciliation: match old and new items by a stable key, reuse the surviving DOM nodes, and emit the minimal inserts, moves, and removals. This is the algorithm behind React's key, Vue's v-for keys, and Snabbdom.
Implement diffDomKeyedReconcile(parent, newKeys, createNode) — reorder a real DOM parent's keyed children to match newKeys, returning the operations performed.
function diffDomKeyedReconcile(parent, newKeys, createNode) {
// returns [{ type: 'insert' | 'move' | 'remove', key }, ...]
}
// parent children (by data-key): a, b, c
diffDomKeyedReconcile(parent, ['c', 'a', 'b'], createNode);
// -> reorders to c, a, b reusing the SAME three nodes; returns move ops
// parent: a, b, c -> new: ['a', 'c']
diffDomKeyedReconcile(parent, ['a', 'c'], createNode);
// -> removes node 'b'; a and c untouched; returns [{ type:'remove', key:'b' }]
data-key. A key present in both lists reuses the same DOM node (preserving its content/state).createNode(key)) for a brand-new key; move reused nodes into place.newKeys — after reconciling, parent's children read exactly newKeys, left to right.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.