A todo list uses useReducer. Items can be marked as done by clicking a button next to each one. Clicking "Complete" on any item has no visible effect — the item never changes appearance.
Click Complete on any todo item — nothing changes. The button responds (no crash, no error) but the item's status never updates on screen.
The reducer runs and returns — so why does React ignore it?
The reducer runs and returns — so why does React ignore it?
Why this fixes it
The `TOGGLE` case wrote directly to `state.items[action.index].done` and then returned the same `state` reference — React compares the object returned by the reducer against the previous state using reference equality, and because it was the exact same object, React concluded nothing had changed and skipped the re-render entirely, leaving the UI frozen despite the internal mutation having occurred. Replacing that with an immutable update — `state.items.map((item, i) => i === action.index ? { ...item, done: !item.done } : item)` wrapped in a new state object — produces a new reference at every level: a new item object, a new items array, and a new state object. React detects the reference change at the top level, schedules a re-render, and the button label and strikethrough style update to reflect the toggled value.