Capítulo 26 de 116
The same read-only rule from Ch 25 applies to arrays in state: never call mutating array methods (push, pop, splice, shift, unshift, direct index assignment, sort/reverse in place) on state — always derive a new array and pass that to the setter.
push()/splice()/arr[i] = x mutate in place and must be avoided on state arrays; [...arr, item]/filter()/map()/slice() all produce a new array and are the correct replacements.setList([...list, newItem]) (append) or [newItem, ...list] (prepend) — spread the existing array into a new one alongside the addition.setList(list.filter(item => item.id !== targetId)) — filter out the item(s) you don't want, rather than splicing the original in place.setList(list.map(item => transform(item))) — map produces a new array; never mutate an item found via .find() and expect the change to register.setList(list.map(item => item.id === targetId ? { ...item, changed: true } : item)) — combines map (new array) with spread (new object per Ch 25) for the one item that changes.[...list.slice(0, i), newItem, ...list.slice(i)]) rather than splice.map for the array layer and spread for the object layer — mutating a nested object even while "correctly" using map on the outer array still breaks the rule if the item itself is mutated in place.useImmer lets nested array-of-objects updates read like direct mutation (draft[i].done = true) while still producing safe, new state under the hood.// Toggle one todo's `done` field without mutating the array or the item
setTodos(todos.map(todo =>
todo.id === targetId ? { ...todo, done: !todo.done } : todo
));
push→spread-append, splice(remove)→filter, in-place edit→map+spread, splice(insert)→slice-and-spread.map) and a new object for the one item that actually changed (via spread).sort() and reverse() mutate in place even though they seem read-only-ish — copy first ([...arr].sort(...)) before calling them on state-derived data.map/filter.key prop these array items need when rendered.