Learning on Web Dev Open is free for all.

Framework Internals > Two hundred lines of frameworkDiffing, and the actual reason keys exist
Phase 04Two hundred lines of framework187 of 434

Diffing, and the actual reason keys exist

Comparing two trees properly is expensive, so every framework cheats in the same two ways, and keys are what you give it in exchange.

Concept16 minAI adversary

Comparing two arbitrary trees for the minimum set of edits is cubic, which is unusable. Every framework therefore makes two assumptions: two elements of different types produce entirely different trees, so on a type change it discards the subtree and rebuilds; and children are matched positionally unless you tell it otherwise. Those assumptions make the whole thing linear and are right almost all the time.

Keys are how you override the positional assumption. A key says "this is the same conceptual item as the one with this key last time", so a reorder becomes a move rather than a rewrite of every node in between. Without keys, inserting at the front of a ten-item list means the framework believes all ten items changed.

The correctness failure is the one that matters, and it is not about speed. Component state, uncontrolled input values, focus and scroll position all live attached to the DOM node or the component instance, and the key decides which item those belong to. Use the array index as a key, delete the first row, and the second row’s half-typed text is now sitting in the first row’s input. It looks like a data bug and it is an identity bug.

You should now be able to

  • Explain the two heuristics that make reconciliation linear
  • Say precisely what goes wrong when a list index is used as a key
Ask the community

Loading…