immutability
Never mutate state directly
React detects changes by comparing references, not internal values. If you mutate an array or object directly, the reference stays the same and React doesn't know anything changed — the component won't re-render.
The problem
Operations like array.push(), array.splice(), or obj.property = value modify the original object in memory. Since the reference doesn't change, React assumes the state is identical to the previous one and skips the re-render. The bug is silent: the logic runs, but the UI doesn't update.
The solution
Always create a new reference when updating state. For arrays use spread [...arr, newItem], arr.filter(), or arr.map() — they all return a new array. For objects use { ...obj, field: value }. For nested structures, copy at every level that changes.
Common pitfalls
- 01array.push(), array.pop(), array.splice(), and array.sort() all mutate the original array — never call them directly on state.
- 02For nested objects you must copy at each level: { ...obj, nested: { ...obj.nested, field: value } }. Consider Immer if the structure is deeply nested.
- 03structuredClone() performs a deep copy but is expensive — use it only when you need to clone a complex object you can't copy level by level.
