1

I'm trying to understand why this example is a good idea. I'm learning React and I found this function which changes the complete property from todo. My question is why this would work? Because we have the const todo which is the one being changed in reality, not the newTodoList which is the one that we return back. I'm guessing that the respective todo from newTodoList is changed as well somehow but I don't undertand how this works because again, we changed the newly created const todo

function toggleTodo(id){
    const newTodoList = [...todos] 
    const todo = newTodoList.find(todo => todo.id === id)
    todo.complete = !todo.complete
    setTodos(newTodoList)
  }
Sss
  • 49
  • 7
  • 1
    It has to do with how JavaScript objects (and arrays) work. This technically mutates state, which is bad, but since it mutates a nested object it does not affect React's ability to re-render. It is also why it is able to modify the new state while only mutating the old state. – Brian Thompson Aug 30 '21 at 20:55
  • @Brian Thompson the state is `[...todos]` so from what I understood it doesn't mutate it, it makes a clone – Sss Aug 30 '21 at 20:59
  • 1
    It makes a *shallow* clone. Nested objects/arrays are not new instances, they retain the same object references. There's some running examples in [this answer](https://stackoverflow.com/questions/59738516/component-wont-update-when-a-redux-state-change-occurs/59738588#59738588) (under "Explanation") that may help show what I mean. – Brian Thompson Aug 30 '21 at 21:00
  • That's helpful thanks! – Sss Aug 31 '21 at 20:15

1 Answers1

2

According to MDN Web Docs on const, The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable—just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.

Since const todo is an object, you can change its properties (i.e. todo.complete)

kimbaudi
  • 13,655
  • 9
  • 62
  • 74
  • 2
    So I 'm understanding that `const todo` holds a reference to a value from `newTodoList` so then when we change the `complete` property we actually change it in `newTodoList` through this – Sss Aug 30 '21 at 21:08
  • 1
    Yes, you are correct. `const newTodoList = [...todos]` creates an array of objects So, `const todo` holds a reference to an object from `newTodoList`. So when you change the `complete` property in `todo`, it also changes it in `newTodoList`. – kimbaudi Aug 30 '21 at 22:00