I'm looking for a function identical to lodash's _.set
except it should return a new object without modifying the original. Are there any implementations of this?
Right now I'm deep-cloning and then setting:
let data = _.cloneDeep(this.state.data);
_.set(data, name, value);
this.setState({data})
But I don't think it's necessary to do a full deep clone, we'd just need to do a shallow clone of the object at the deepest level, no?
e.g.
let oldData = { 'a': [{ 'b': { 'c': 3 }, 'd': {'e': 4} }] };
let newDate = withValue(oldData, 'a[0].b.c', 5);
The proposed withValue
function would perform a shallow clone of a
, a[0]
and a[0].b
and then modify the new a[0].b.c
to 5. We would not need to make a copy of a[0].d
.
This is going to be a multi-part answer.
Immutable set:
As you're using lodash, you can use the FP version of lodash and use .set
(or .setWith
to be able to supply an object path) which will do an immutable update.
Or, as this looks like a React codebase you can use the $set
helper of React.
Or you can just use the Spread Operator:
const newObj = {...oldObj, prop: newValue }
Or Object.assign:
const newObj = Object.assign({}, oldObj, { prop: newValue });
Performance:
As you're mentioning performance (and not just deeply cloning an object) you might want to look in to an immutable framework. The more developed codebases increase performance by different measures. E.g. here's what immutable.js says:
These data structures are highly efficient on modern JavaScript VMs by using structural sharing via hash maps tries and vector tries
...and Mori says:
Efficient immutable data structures - no cloning required [...] Modern JavaScript engines like V8, JavaScriptCore, and SpiderMonkey deliver the performance needed to implement persistent data structures well.
lodash/fp as Emil suggested should work.
Example:
const setIn = require('lodash/fp/set');
this.setState({data: setIn(name, value, this.state.data)});
N.B. the argument order is different than regular lodash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With