A Cautionary tale about the spread operator
I have been using the ES6 syntax for making copies of objects when React/Redux demanded we return a new copy every time we made a change to the state.
This syntax is
const newState = {
...state,
keyToChange: changedValue,
};
This works great because the spread operator creates a copy of all the keys in the original object. Except… Something that is easy to forget is that it is a shallow copy.
This means that if we have a nested object, the 1st level will be copied by value but every level that’s further nested will be copied by reference! Who would have thunk?
Take a look at this example
const newState = { ...state };
newState['controls']['nightMode'] = true;
We would assume that we get a new object to play with as we deem fit. But if we change a value that’s 2 levels deep as above, we end up mutating the original object and React/Redux will not work as expected because they depend on brand new objects that they can compare with the old objects.
Instead we could do something like
const newState = {
...state,
controls: {
...state.controls,
darkMode: true,
},
};
Notice we are using the spread operator at every level of nesting.
In summary, remember that the spread operator gives you a shallow copy. Also, keep your redux state as flat as possible so you don’t have to deal with such situations. Happy coding!