Question presented to candidate: "You have a Redux-style reducer that does const newState = { ...state } and then calls newState.items.sort(). What is wrong with that, and how does toSorted() fix it?"
What a strong answer should cover:
- Array.prototype.sort() sorts the array in place and returns the SAME array reference -- it does not create a new array.
- A shallow spread like { ...state } only copies the top-level properties of state; if items is an array, the new object's items property still points at the exact same array as the old state's items -- spreading an object never clones the arrays or objects nested inside it.
- Combining those two facts produces the real bug: newState.items.sort() mutates the one shared array, so the OLD state object's items also changes -- silently corrupting what should have been an immutable snapshot of the previous state.
- Array.prototype.toSorted(), added in ES2023, sorts into a brand-new array and leaves the source untouched, so newState.items = state.items.toSorted() produces a new array reference without touching the old state at all.
- This directly matters for React and Redux because both rely on reference equality (Object.is) to detect whether something changed -- a mutated-in-place array keeps the same reference, so a reference-equality check would not even notice the array changed, potentially skipping a needed re-render.
Clarifying questions expected:
- "Is the concern here the mutation itself, or specifically its effect on React or Redux change detection?"
- "Does the comparator function need to match exactly what .sort() was already using?"
Code / implementation expected: Yes -- a real, executed reducer example showing .sort() corrupting old state through a shallow spread, contrasted with a toSorted()-based version that leaves old state genuinely untouched.