I am trying to create a deep copy map method for my Redux project that will work with objects rather than arrays. I read that in Redux each state should not change anything in the previous states.
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
output[key] = callback.call(this, {...object[key]});
return output;
}, {});
}
It works:
return mapCopy(state, e => {
if (e.id === action.id) {
e.title = 'new item';
}
return e;
})
However it does not deep copy inner items so I need to tweak it to:
export const mapCopy = (object, callback) => {
return Object.keys(object).reduce(function (output, key) {
let newObject = {...object[key]};
newObject.style = {...newObject.style};
newObject.data = {...newObject.data};
output[key] = callback.call(this, newObject);
return output;
}, {});
}
This is less elegant as it requires to know which objects are passed. Is there a way in ES6 to use the spread sign to deep copy an object?
No such functionality is built-in to ES6. I think you have a couple of options depending on what you want to do.
If you really want to deep copy:
cloneDeep
method.Alternative Solution To Your Specific Problem (No Deep Copy)
However, I think, if you're willing to change a couple things, you can save yourself some work. I'm assuming you control all call sites to your function.
Specify that all callbacks passed to
mapCopy
must return new objects instead of mutating the existing object. For example:This makes use of
Object.assign
to create a new object, sets properties ofe
on that new object, then sets a new title on that new object. This means you never mutate existing objects and only create new ones when necessary.mapCopy
can be really simple now:Essentially,
mapCopy
is trusting its callers to do the right thing. This is why I said this assumes you control all call sites.From MDN
Personally, I suggest using Lodash's cloneDeep function for multi-level object/array cloning.
Here is a working example:
I often use this:
Instead use this for deep copy