You did not state the immutable.js version you used, but the way you asked, it is probably 4.0.0-rc12. The mergeDeep function of Immutable.js version 3.8.x did what you want; It replaced arrays instead of merging them. That's why @etarhan's answer works but does not for you.
There is no "nice" solution. The mergeDeepWith
function let's you define a merger function, but sadly the merger is only triggered on conflicts - so it does not help you either. All you can do is walk the object manually or upgrade immutable.js.
Also note that Immutable.Map({ a: { x: 1, z: 1, y: 1, values: [1, 2, 3] } });
does only convert the input shallowly. The array of values
stays an array. That is often undesired, you would want to have an Immutable.List instead of an array. To do so, use fromJS
, which converts depply.
I'll bring this up on the slack channel, IMO there should be the possbility to call the merger on collections too.
Something similar to this might do the job:
const map1 = Immutable.fromJS({ a: { x: 'one', z: 'old', y: 'old', values: [1, 2, 3] } });
const map2 = Immutable.fromJS({ a: { x: 'two', v: 'new', values: [4, 5, 6] } });
function mergeStuff(a, b, path = '') {
return a.withMutations(map => {
for(key of b.keys()) {
map.update(key, (val) => {
console.log('updating', path + key, val, b.get(key));
if(Immutable.isKeyed(val)) {
return mergeStuff(val, b.get(key), key + '.');
}
return b.get(key, val);
});
}
});
}
const map3 = mergeStuff(map1, map2);
console.log('result:');
console.log(map3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/4.0.0-rc.12/immutable.js"></script>