Reputation: 338
a redux noob here.
In redux tutorial in this part particularly Why they didn't do something like that
case 'todos/todoToggled': {
return {
...state,
todos: state.todos.map(todo => {
if (todo.id === action.payload.todoId) {
todo.completed = !todo.completed
}
return todo
}
)
}
As far as I know map()
doesn't have any side effects quoted from Mozilla docs
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
Why they did this extra step?
// We've found the todo that has to change. Return a copy:
return {
...todo,
// Flip the completed flag
completed: !todo.completed
}
Will it affect the functionality? or they just want to be consistent?
Upvotes: 0
Views: 72
Reputation: 50759
As far as I know
map()
doesn't have any side effects
It can have side-effects, that fact that the map method creates a new array doesn't mean it can't have any side effects. For example:
const arr = [{x: 1}, {x: 2}, {x: 3}];
const newA = arr.map(obj => {
obj.x += 1; // changes the objects in `arr`
return obj;
});
console.log(newA); // new array (objects are still references to original ones)
console.log(arr); // Also changed!
The map function gets passed a reference to each object, meaning that when you change obj
, it also changes it within the original array. As a result, when you do:
todo.completed = !todo.completed
you're changing the todo
objects in your array, which results in you changing your state directly.
Unlike the above, the presented code:
{
...todo,
completed: !todo.completed
}
does not change the todo
object reference, but rather, it takes all the (enumerable own) keys from it and puts it in a new object, which also overwrites the completed
key to hold the negated (ie: opposite) completed
boolean value.
Upvotes: 5