2
const List = Immutable.List;
const items = [
  { id: 1, subList: [] }, 
  { id: 2, subList: [] }, 
  { id: 3, subList: [] }
];
const newItem = { name: "sublist item" };

let collection = List(items);

collection = collection.updateIn([0, 'subList'], function (items) {
  return items.concat(newItem)
});

https://jsbin.com/midimupire/edit?html,js,console

Results in:

Error: invalid keyPath

I think that perhaps I need to set subList as a List(); I get the same error when trying this.

3
  • Which key is causing the error? Commented Oct 9, 2017 at 12:53
  • Difficult to tell (github.com/facebook/immutable-js/issues/635). I know from running this locally with the most up to date Immutable, the issue is [0] cannot be Set Commented Oct 9, 2017 at 13:01
  • Change the updateIn to getIn, and try removing the "subList" key. Does it return the first map? Commented Oct 9, 2017 at 13:02

3 Answers 3

3

If I understand the question correctly, you want to return collection with the first element as:

{
  id : 1,
  subList: [
    {name: "sublist item"}
  ]
}

To do this we'll need to make a few changes.

  1. Use Immutable.fromJS to deeply convert the plain JS array of objects to an Immutable List of Maps

  2. Use List.update() to return a new List with the updated value

  3. Use Map.updateIn() to return a new LMapist with the updated value

Here's the whole thing:

const List = Immutable.List;
const items = [{
    id: 1,
    subList: []
  },
  {
    id: 2,
    subList: []
  },
  {
    id: 3,
    subList: []
  }
];
const newItem = {
  name: "sublist item"
};

let collection = Immutable.fromJS(items);

collection = collection.update(0, item => {
  return item.updateIn(['subList'], subList => {
    return subList.concat(newItem);
  });
});

console.log(collection)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>

And the result:

[
  {
    "id": 1,
    "subList": [
      {
        "name": "sublist item"
      }
    ]
  },
  {
    "id": 2,
    "subList": []
  },
  {
    "id": 3,
    "subList": []
  }
]

Update: List.updateIn() can use an index as the keypath, so you can simplify this to the following:

collection = collection.updateIn([0, 'subList'], subList => {
  return subList.concat(newItem);
});

Like this:

const List = Immutable.List;
const items = [{
    id: 1,
    subList: []
  },
  {
    id: 2,
    subList: []
  },
  {
    id: 3,
    subList: []
  }
];
const newItem = {
  name: "sublist item"
};

let collection = Immutable.fromJS(items);

collection = collection.updateIn([0, 'subList'], subList => {
  return subList.concat(newItem);
});

console.log(collection)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

0

Use the object you got, update the subArray and return the whole object.

const List = Immutable.List;
const items = [
  { id: 1, subList: [] }, 
  { id: 2, subList: [] }, 
  {id: 3, subList: [] }
];
const newItem = { name: "sublist item" };

let collection = List(items);

collection = collection.update([0], function (obj) {
   obj.subList = obj.subList.concat(newItem)
   return obj;
});

Comments

0

This doesn’t work because the elements of your Immutable.List are plain-old JavaScript objects (POJO), not Immutable.Maps, so updateIn doesn’t know how to work with them. You can either:

  • Make the objects Immutable.Maps by using Immutable.fromJS instead of Immutable.List as the constructor to convert the entire object graph to Immutable objects. (See JS Bin)
  • Use update([0]) instead of updateIn to just get the POJO and mutate it (as in @Navjot’s answer).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.