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.