laprof
laprof

Reputation: 1344

Cannot access properties of Immutable.js map

I use Immutable.js to deserialize stored maps. Unfortunately I have not yet managed to access properties of the map. If I run the code like below, I get the right map entry. If I try to access the property name, I get an undefined object. I'm new to JS and haven't quite figured out how to access the entries yet.

I get this object back if I run the following code. How can I access the name now?

let map: Immutable.Map<string, User> = Immutable.fromJS(users[index].userMap).toMap();
console.log(map.get("4");
Map {size: 2, _root: ArrayMapNode, __ownerID: undefined, __hash: undefined, __altered: false}
  size: 2
  _root: ArrayMapNode
    ownerID: OwnerID {}
    entries: Array(6)
      0: (2) ["name", "joe"]
      1: (2) ["text", "test"]
      length: 2
      __proto__: Array(0)
  __proto__: Object
  __ownerID: undefined
  __hash: undefined
  __altered: false
  state: true
__proto__: KeyedCollection

User

export interface User {
  name: string;
  text: string;
}
userMap: Immutable.Map<string, User>;

Upvotes: 3

Views: 1298

Answers (1)

dube
dube

Reputation: 5019

Issues with access

Using typescript tricked you into thinking that that map actually contains User. It does not. Immutable.fromJS deeply converts objects to maps, unless the objcts are Immutable objects (e.g. Map, List, Record,...).

You even saw it when console.log(map.get("4")); returned an Immutable.Map.

So to access it, treat them like nested maps: map.getIn(["4", "name"]); Or convert the Users to Immutable.Records before adding them to the map:

const UserRecord = Record({ name: undefined, text: undefined });
Immutable.Map(users[index].userMap.map(entry => UserRecord(entry));
console.log(map.get("4").name);

Issues with modification

It's working now with map.getIn(["4", "name"]);, but I cannot use setIn(["4", "name"], "newName"). it just won't update the name.

You might not have fully understood how immutable works. Immutable objects never change (that's the whole point!). map.setIn(["4", "name"], "newName") will not change anything, it returns a new map that contains the updated data! You would have to assign it to something to see the updated data, e.g.

const changedMap = map.setIn(["4", "name"], "newName");

Upvotes: 2

Related Questions