React state updates must be immutable: never mutate arrays or objects in place. Create new references so React detects change and re-renders predictably.
Array updates
- Add:
[...items, newItem] - Remove:
items.filter((x) => x.id !== id) - Update one:
items.map((x) => x.id === id ? { ...x, done: true } : x)
Object updates
Shallow copy with spread: setUser((u) => ({ ...u, name: 'New' })). Nested structures need copying each level you change.
Important interview questions and answers
- Q: Why not push to state array directly?
A: Mutating the same reference may skip re-render and breaks time-travel debugging tools. - Q: immer or immutable libraries?
A: Optional sugar for complex nested updates; spread/filter/map are enough for most app code.
Self-check
- How do you toggle a todo’s
doneflag immutably? - What is wrong with
items.sort()on state directly?
Challenge
Toggle todo
- Click a todo label to toggle
done. - Confirm completed items get line-through style.
Done when: each todo toggles independently without mutating the array.