Props and state
Update objects and arrays without mutation
Create a new value for state so React receives a changed reference and previous render snapshots remain reliable.
Treat objects and arrays in state as immutable snapshots. Create the next value instead of changing the current one.
This mutation is a bug:
tasks[0].done = true
setTasks(tasks)
The array reference has not changed, and an object used by an earlier render was modified in place.
Use non-mutating array methods and object spread:
setTasks(currentTasks =>
currentTasks.map(task =>
task.id === id
? { ...task, done: true }
: task
)
)
The new array contains a new object for the changed task. Unchanged task objects keep their existing references.
Spread is shallow. For nested data, copy every changed level:
setUser(user => ({
...user,
address: {
...user.address,
city: 'Copenhagen'
}
}))
Keep state shapes simple. Deeply nested state makes updates harder and increases the chance of accidental mutation.
For arrays, use map() to replace, filter() to remove, and spread to add. Avoid mutating methods such as push(), pop(), and splice() on state arrays.
Log the old and new references with ===. The array and changed object should differ; unchanged objects can remain equal.
Lesson completed