Svelte Keyed each: Identity, Not Index
Svelte keyed each blocks track list items by identity, not index. Without a key, reordering or filtering leaves component state attached to the wrong DOM position. Using the array index as the key silently defeats the purpose and preserves the bug.
WHY IT EXISTS: When a list of data changes, a framework must decide whether to recycle existing DOM nodes or tear them down and build fresh ones. Reusing nodes by index is fast but dangerous: if items shift order, any local state, focus, or animations tied to those nodes become detached from the data they represent. Svelte keyed each blocks were created to solve this mismatch by letting you declare a stable identity for every row, so the framework can match elements to their correct logical records across updates.
THE MENTAL MODEL: Think of a keyed list as a coat-check system. The ticket number is tied to your specific coat, not to the hook it hangs on. If the attendant rearranges coats on the rack, the ticket still leads you to the right garment. In Svelte, the key is that ticket; it tells the framework which component or element belongs to which data object regardless of where it currently sits in the array.
HOW IT WORKS: In a standard each block, Svelte diffs lists by index. It updates the first DOM node with the first item, the second node with the second item, and so on, mutating values in place. When you provide a key expression inside parentheses, such as {#each items as item (item.id)}, Svelte constructs an internal map from key values to rendered nodes and component instances. On every update, it compares the new key set against the old one to detect additions, removals, and reorderings. It then inserts moved nodes into their new positions, destroys nodes whose keys vanished, and mounts fresh ones for new keys, preserving internal state for anything that merely changed position.
WHEN TO USE IT: Use a key whenever list items carry identity beyond their current slot. Three common situations demand it: first, reordering via drag-and-drop or sort buttons; second, filtering where items disappear and later reappear; third, when each row is a component with its own local state, form inputs, focused elements, or animations that must remain bound to the same logical record no matter how the surrounding list changes.
WHEN NOT TO USE IT: Skip keys if the list is completely static and stateless, or if items are ephemeral computed values that never reorder and hold no local state. More importantly, never use an unstable key. Random values, timestamps, or the array index itself are traps. An index key pretends to provide identity while actually tracking position, which silently negates the entire benefit and can degrade performance by forcing unnecessary component teardown and recreation on every update.
ONE CANONICAL EXAMPLE: Imagine a task board where each card is a Svelte component with an internal isEditing flag and a text input. If you sort cards by priority without a key, the isEditing state and the input cursor stay glued to the first DOM node. The user ends up editing the wrong task after the sort. Adding (task.id) to the each block ensures the component and its state travel with the specific task, no matter how the board is reordered.
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.