2

My array of objects contains objects of different kinds, meaning they can have very different properties. However they all share an id property.

When my app's user wants to update one of these objects, I need to find that object in the array based on the id and update all its properties, probably using Object.assign().

I know how to find and return the object I want based on the id, but not how to update it as well. Any idea?

let myArray = [
  {
    id: 1,
    name: 'john',
    age: '22',
    position: 'developer'
  },
  {
    id: 2,
    name: 'james',
    age: '31',
    position: 'designer'
  },
  {
    id: 1,
    name: 'david',
    age: '45',
    position: 'teacher'
  }
]

let updateForJames = {
    age: '38',
    position: 'project manager'
}

let JamesId = 2

Object.assign(myArray, {
    // ...
})

JSFiddle

drake035
  • 3,955
  • 41
  • 119
  • 229
  • Does this answer your question? [How to change value of object which is inside an array using JavaScript or jQuery?](https://stackoverflow.com/questions/4689856/how-to-change-value-of-object-which-is-inside-an-array-using-javascript-or-jquer) –  Dec 22 '19 at 12:24

1 Answers1

3

If you're happy with changing the array in-place you can use .find() to find the object with the given id, and then update that object using Object.assing() like so:

const myArray = [{ id: 1, name: 'john', age: '22', position: 'developer' }, { id: 2, name: 'james', age: '31', position: 'designer' }, { id: 1, name: 'david', age: '45', position: 'teacher' }];
const updateForJames = {
  age: '38',
  position: 'project manager'
}
const JamesId = 2;

const jamesobj = myArray.find(({id}) => id === JamesId) || {};
Object.assign(jamesobj, updateForJames);
console.log(myArray);

Alternatively, if you want to get a new array (rather than modifying it in place) you can .map() each object to a new object, and add the new contents in updateForJames when james's id appears using the spread syntax:

const myArray = [{ id: 1, name: 'john', age: '22', position: 'developer' }, { id: 2, name: 'james', age: '31', position: 'designer' }, { id: 1, name: 'david', age: '45', position: 'teacher' }];
const updateForJames = {
  age: '38',
  position: 'project manager'
}
const JamesId = 2;

const new_array = myArray.map(
  ({id, ...r}) => id === JamesId ? {id, ...r, ...updateForJames} : {id, ...r}
);
console.log(new_array);
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • Thanks! It works however I don't understand why: I'm using first option as I need to change the array in place, but you're using `Object.assign()` on `jamesobj` not on the array in place, so how can the latter be modified? I dont' get it – drake035 Dec 22 '19 at 13:14
  • 1
    So `.find()` returns a reference to the object inside the array. This means when you change a property on this reference you're actually changing the object inside the array. `Object.assign()` allows us to change multiple properties at once in the reference (and thus the object inside the array) – Nick Parsons Dec 22 '19 at 13:16
  • So it's a similar idea to what's happening [here](https://jsfiddle.net/ws5q3gtj/), just `Object.assign()` allows us to change multiple properties at once on the reference rather than just one property at a time – Nick Parsons Dec 22 '19 at 13:20
  • 1
    Thanks for the clarification, now I got it :) – drake035 Dec 22 '19 at 13:22
  • @drake035 no worries ;) – Nick Parsons Dec 22 '19 at 13:23
  • I'm having trouble implementing that code though, could you kindly take a look at https://jsfiddle.net/phrw0j7u/ and see why the incorrect object get updated please? (also I don't understand something: if I display the array BEFORE making the change, it STILL displays the change. To prevent this, I need to wait 2 seconds before making the change and only then the first display correctly shows shows the array as it was before the change) – drake035 Dec 22 '19 at 14:09
  • You're missing the `id ==` in your `.find()` function. https://jsfiddle.net/wf28gs3q/ – Nick Parsons Dec 22 '19 at 14:11
  • basically, when the the `find` function loops through every object in the array. For each object we pull out its `id` property (using destructuring assignment). Then we check if it is equal to the wanted (in your case the string id). When the inner function returns `true` it returns a reference to the current object it is iterated on – Nick Parsons Dec 22 '19 at 14:13
  • @drake035 the issue with the array changing before you make the change is because the console itself doesn't log a "snapshot" of the array like you might think. Instead, it logs a reference to the array. This we change the array in place, you'll see both change. It's explained better [here](https://stackoverflow.com/questions/23429203/weird-behavior-with-objects-console-log) – Nick Parsons Dec 22 '19 at 14:15
  • 1
    What a stupid omission from me, sorry for that. Works now and I also see now the reason behind that weirdness in the console. Thanks a lot and have a nice day! – drake035 Dec 22 '19 at 14:17
  • @drake035 no worries. One way you can get around the reference issue (and if you want to log a "snapshot" of the current state) is to use `JSON.stringify()` on your array ([here](https://jsfiddle.net/wf28gs3q/1/) is an example) – Nick Parsons Dec 22 '19 at 14:21