44
var a = {address: {postcode: 5085}}

var b = Immutable.fromJS(a)
var c = b.setIn(['address', 'suburb'], 'broadview').toJS(); // no error
console.log(c); 

var d = Immutable.Map(a);
var e = d.setIn(['address', 'suburb'], 'broadview').toJS(); // error invalid keyPath(…)

Could someone explain the difference.

Thanks,

T. Junghans
  • 11,385
  • 7
  • 52
  • 75
sowdri
  • 2,193
  • 5
  • 23
  • 36

2 Answers2

86

In this example,

var a = {address: {postcode: 5085}}
var d = Immutable.Map(a);

Here, d.get('address') is immutable. It's value cannot change to any other objects. We can only create a new Object from the existing object using the Immutable.Map.set() function of ImmutableJS.

But, the object referenced by d.get('address') i.e, {postcode:5085} is a standard JavaScript object. It is mutable. A statement like this can alter the value of postcode:

d.get('address').postcode=6000;

If you check the value of d again, you can see that he value has been changed.

console.log(JSON.stringify(d));   //Outputs {"address":{"postcode":6000}}

which is against the principles of immutability.

The reason is that ImmutableJS data structures like List and Map imparts the immutability feature to only the level-1 members of the List/Map.

So, if you have objects inside arrays or arrays inside objects and want them too to be immutable, your choice is Immutable.fromJS.

var a = {address: {postcode: 5085}}
var b = Immutable.fromJS(a);
b.get('address').postcode=6000;
console.log(JSON.stringify(b));   //Outputs {"address":{"postcode":5085}}

From the above example you can clearly know how fromJS makes the nested members immutable.

I hope you understood the difference between Map and fromJS. All the best =)

Yonggoo Noh
  • 1,811
  • 3
  • 22
  • 37
Samu
  • 1,448
  • 10
  • 14
  • 2
    omg, thank you so much for explaining this! i've been struggling with this, and i finally understand why my map.get(k) was returning by reference (and how to avoid it without doing some kind of stupid deepCopy(map.get(k)). – grendian Apr 29 '16 at 15:52
  • Excellent! The Immutable.js Map docs aren't clear of this core difference to fromJS: https://facebook.github.io/immutable-js/docs/#/Map – Tom McKenzie Aug 30 '16 at 05:37
25

fromJS does a deep conversion. That is, it'll recurse through all the keys and convert all elements to Lists, Maps, etc.

In your second example, address is a plain object, not an ImmutableJS object, so you cannot use setIn to change its value.

eipark
  • 7,442
  • 3
  • 24
  • 33
timetofly
  • 2,957
  • 6
  • 36
  • 76