Why does this reducer mutate earlier snapshots even though I spread the array?

I’m keeping a history of states for undo, but older snapshots change when I update a nested item. I thought spreading the array was enough. What’s the minimal fix here without pulling in Immer?

const history = [[{ id: 1, done: false }]];

function nextState(prev) {
  const copy = [...prev];
  copy[0].done = true;
  return copy;
}

history.push(nextState(history[0]));
console.log(history[0][0].done, history[1][0].done);

Why do both values become true, and what’s the safest plain-JS pattern for nested updates in reducers?

Quelly

[...prev] only clones the outer array, so copy[0] is still the same object as prev[0].

Sora