Parent tracking issue: #1455
Summary
Resolve all 34 `@eslint-react/no-array-index-key` warnings. Using the array index as a React `key` causes mis-reconciliation when items are reordered, inserted, or removed — React reuses the wrong DOM nodes and component state.
Fix patterns (in priority order)
- Stable domain key — if items have an `id`, slug, or other unique field, use it.
- Composite stable key — combine domain fields (e.g., `${vendor}-${date}`) when no single field is unique.
- Generated stable key — for items that genuinely lack any natural key (rare), generate one at creation time:
```tsx
const items = useMemo(
() => rawItems.map((item) => ({ ...item, _key: crypto.randomUUID() })),
[rawItems]
);
```
Note: the `useMemo` is critical — without it, you'd regenerate keys on every render and re-mount every child.
Scope
Production code (`client/src/`).
Acceptance Criteria
Risk
Medium. Each fix is small, but mis-keyed lists can mask subtle state bugs. Verify lists that have any inline UI state (open menus, focused inputs).
Parent tracking issue: #1455
Summary
Resolve all 34 `@eslint-react/no-array-index-key` warnings. Using the array index as a React `key` causes mis-reconciliation when items are reordered, inserted, or removed — React reuses the wrong DOM nodes and component state.
Fix patterns (in priority order)
```tsx
const items = useMemo(
() => rawItems.map((item) => ({ ...item, _key: crypto.randomUUID() })),
[rawItems]
);
```
Note: the `useMemo` is critical — without it, you'd regenerate keys on every render and re-mount every child.
Scope
Production code (`client/src/`).
Acceptance Criteria
Risk
Medium. Each fix is small, but mis-keyed lists can mask subtle state bugs. Verify lists that have any inline UI state (open menus, focused inputs).