sumi

Basics · Logic

Keyed loops

Without a key, list items diff by position: the box at index 0 is compared with the new index 0, and so on. Reorder or insert near the front and every item from the first change onward is rebuilt.

Adding key=expr to the range clause matches items by identity across renders instead. When the list reorders, each item’s existing box is found by its key and moved rather than rebuilt — so per-item state that lives in the tree, like an input’s edit cursor or which item has focus, travels with the item instead of staying pinned to a position.

Use a key that is stable and unique per item — a record ID, not the array index. The Task type here has an ID field for exactly this.

Your turn

Add a key to the loop. Change the range clause to end with key=task.ID:

{for _, task := range tasks.Get() key=task.ID}

The output looks the same now, but the list is ready to reorder without losing per-item state. Press Run to confirm it still builds. Solve shows the finished version; Reset restores the start.

⌘↵ to run