I'm confused by this section of the immer docs. I created a simpler example to test the same principle, i.e. to add some new object to the draft data structure and then modify it. Which according to the docs should also modify the original data structure:
import { produce } from "immer";
function print(obj) {
console.log(JSON.stringify(obj));
}
var todos = [
{ id: 0, done: false },
{ id: 1, done: false }
];
function onReceiveTodo(todo) {
return produce(todos, draft => {
draft[1] = todo;
draft[1].done = true;
});
}
let nextTodos = onReceiveTodo({ id: 3, done: false });
print(todos);
print(nextTodos);
// [{"id":0,"done":false},{"id":1,"done":false}] // todos
// [{"id":0,"done":false},{"id":3,"done":true}] // nextTodos
But this seems to work.
Could someone please explain this pitfall in a bit more detail?
Note: I also tried to use the exact same example that was in the docs, but was confused about what the data structure todos
is supposed to look like. Since draft
is bound to the original version of todos
, this line: draft.todos[todo.id] = todo
suggests that we have something like todos = {todos: {0: {done: false}, 1: {done: false},...}
, but todo.id
suggests that a todo
object contains the id
.
It's about "if you pass and mutate an object inside
produce
it is in fact mutated".Basically when you do:
The original object can be changed. Consider instead: