Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Use stable keys for dynamic lists
Stable keys preserve correct component state when lists reorder, filter, or mutate.
Bad example
| 1 | import { useState } from "react"; |
| 2 |
|
| 3 | type Item = { id: string; label: string }; |
| 4 |
|
| 5 | export function List({ items }: { items: Item[] }) { |
| 6 | const [values, setValues] = useState<Record<string, string>>({}); |
| 7 |
|
| 8 | return ( |
| 9 | <ul> |
| 10 | {items.map((item, index) => ( |
| 11 | <li key={index}> |
| 12 | <input |
| 13 | value={values[item.id] ?? ""} |
| 14 | onChange={(e) => setValues((v) => ({ ...v, [item.id]: e.target.value }))} |
| 15 | /> |
| 16 | <span>{item.label}</span> |
| 17 | </li> |
| 18 | ))} |
| 19 | </ul> |
| 20 | ); |
| 21 | } |
Explanation (EN)
Using array indices as keys breaks reconciliation when items reorder or are inserted/removed. Inputs can appear to 'swap' values or keep the wrong state.
Objašnjenje (HR)
Koristenje indexa kao key-a kvari reconciliation kada se lista sortira ili se elementi ubacuju/brišu. Inputi mogu 'zamijeniti' vrijednosti ili zadrzati krivi state.
Good example
| 1 | import { useState } from "react"; |
| 2 |
|
| 3 | type Item = { id: string; label: string }; |
| 4 |
|
| 5 | export function List({ items }: { items: Item[] }) { |
| 6 | const [values, setValues] = useState<Record<string, string>>({}); |
| 7 |
|
| 8 | return ( |
| 9 | <ul> |
| 10 | {items.map((item) => ( |
| 11 | <li key={item.id}> |
| 12 | <input |
| 13 | value={values[item.id] ?? ""} |
| 14 | onChange={(e) => setValues((v) => ({ ...v, [item.id]: e.target.value }))} |
| 15 | /> |
| 16 | <span>{item.label}</span> |
| 17 | </li> |
| 18 | ))} |
| 19 | </ul> |
| 20 | ); |
| 21 | } |
Explanation (EN)
Stable unique keys (item.id) let React correctly preserve state per item across reorders and mutations.
Objašnjenje (HR)
Stabilni jedinstveni key-evi (item.id) omogucuju Reactu da ispravno sacuva state po elementu kroz reorder i promjene liste.
Notes (EN)
If you don't have stable IDs, generate them at the data layer (not at render time) so they remain stable across renders.
Bilješke (HR)
Ako nemas stabilne ID-eve, generiraj ih na data layeru (ne u renderu) da ostanu stabilni kroz rendere.
Exceptions / Tradeoffs (EN)
Indices are acceptable only for fully static lists that never reorder, insert, or delete items.
Iznimke / Tradeoffi (HR)
Indexi su prihvatljivi samo za potpuno staticke liste koje se nikad ne reorderaju, ne ubacuju i ne brisu.