<For> vs <Index>: Keyed by Item Reference vs Keyed by Array Index
- Last updated
- Prerequisites:
- SolidJS Components and JSX
- Array manipulation in signals
- solidjs
- control-flow
- For
- Index
- lists
- performance
Read at your depth
The practical view
Solid provides two built-in list components: `<For>` and `<Index>`. `<For each={items()}>` **keys by object reference**: when items move, reorder, or are inserted, the DOM nodes move with the item, and the item passed to the callback is static while its index is a signal (`item, indexSignal`). `<Index each={items()}>` **keys by array index**: DOM nodes stay fixed at their indices, while the item passed to the callback is a signal (`itemSignal, indexInt`).
The same idea in other frameworks
`{items.map((item, index) => <Item key={item.id} />)}` (equivalent to `<For>`).`@for (item of items; track item.id)` (like `<For>`) vs `track $index` (like `<Index>`).`<div v-for="(item, index) in items" :key="item.id">`.`{#each items as item (item.id)}` (like `<For>`).Legacy vs modern
When to Use <For> vs <Index>
Use `<For>` for lists of objects where element identity matters; use `<Index>` for arrays of primitives to avoid DOM node re-allocations.
<For each={numbers()}>{(num) => <input value={num} />}</For> // ❌ Re-creates DOM node on every edit<Index each={numbers()}>{(numSignal, index) => <input value={numSignal()} />}</Index> // ✅ NEW: Preserves DOM & focusInterview gotchas
Context
Interviewers test your practical attention to detail regarding signal parameters.
The mechanical answer
In `<For each={items}>{(item, index) => ...}</For>`, **`item` is a static value** and **`index` is a reactive accessor signal (`index()`)**. In `<Index each={items}>{(item, index) => ...}</Index>`, **`item` is a reactive accessor signal (`item()`)** and **`index` is a static number**.
Trap
Calling `item()` in a `<For>` loop will cause a `TypeError: item is not a function`. Omitting `()` on `item` in an `<Index>` loop will render the raw function representation instead of the value.
Context
Checks understanding of object reference identity in list reconciliation.
The mechanical answer
Primitives in JavaScript (strings, numbers) are compared by value. When the user types a new character, the string value changes (e.g. `'a'` -> `'ab'`). Because `<For>` tracks identity by reference/value, it considers `'a'` destroyed and `'ab'` a completely new item, destroying the old DOM `<input>` element and creating a new one, which immediately drops keyboard focus.
Trap
Always use `<Index>` when mapping arrays of primitive strings/numbers or when mutating by index.