简体   繁体   中英

Object not replacing using spread operator

I want to replace existing object with new updated fields using spread operator. But I am not getting the correct result.

Below are my two objects.

let obj1 = [
  {
    "id": 1,
    "name": "Michel",
    "age": 34,
    "email": "michel@gmail.com"
  },
  {
    "id": 2,
    "name": "Abby",
    "age": 40,
    "email": "abby@gmail.com"
  },
  {
    "id": 3,
    "name": "Gary",
    "age": 40,
    "email": "abby@gmail.com"
  }
]

let newObj = {
  "id": 3,
  "name": "Gary",
  "age": 23,
  "email": "gary@gmail.com"
}

I can do it with .map. Below is my code.

let result = obj1.map(item => {
  if (item.id === newObj.id) {
    return {...item, ...newObj};
  }
  return item;
});

But I do not want to run the loop and want to acheive by spread operator only.

Example for spread. Which is not working. It's not replacing the object. Instead creating one more.

[...obj1,  newObj];

Can someone help me?

JSBIN CODE SNIPPET

Use Object.assign

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

 let obj1 = [ { "id": 1, "name": "Michel", "age": 34, "email": "michel@gmail.com" }, { "id": 2, "name": "Abby", "age": 40, "email": "abby@gmail.com" }, { "id": 3, "name": "Gary", "age": 40, "email": "abby@gmail.com" } ] let newObj = { "id": 3, "name": "Gary", "age": 23, "email": "gary@gmail.com" } Object.assign(obj1[2], newObj); console.log(obj1) 

Using .find() to get the target obj

 let obj1 = [ { "id": 1, "name": "Michel", "age": 34, "email": "michel@gmail.com" }, { "id": 2, "name": "Abby", "age": 40, "email": "abby@gmail.com" }, { "id": 3, "name": "Gary", "age": 40, "email": "abby@gmail.com" } ] let newObj = { "id": 3, "name": "Gary", "age": 23, "email": "gary@gmail.com" } const targetObj = obj1.find(obj => obj.id === newObj.id) Object.assign(targetObj, newObj); console.log(obj1) 

Spread syntax doesn't replace the object within array like you used it. Using map is the simplest and understandable way. However if you want to use spread syntax you would first need to find the index to be replaced and then use slice on array

 let obj1 = [ { "id": 1, "name": "Michel", "age": 34, "email": "michel@gmail.com" }, { "id": 2, "name": "Abby", "age": 40, "email": "abby@gmail.com" }, { "id": 3, "name": "Gary", "age": 40, "email": "abby@gmail.com" } ] let newObj = { "id": 3, "name": "Gary", "age": 23, "email": "gary@gmail.com" } const idx = obj1.findIndex(item => item.id === newObj.id); obj1 = [...obj1.slice(0, idx), newObj, ...obj1.slice(idx + 1)]; console.log(obj1); 

Spread operator is magic but it won't do whatever you want, you will have to loop over and replace the object. Instead of doing a map() , I would prefer find() . The use Object.assign() to achieve what you want.

 let obj1 = [ { "id": 1, "name": "Michel", "age": 34, "email": "michel@gmail.com" }, { "id": 2, "name": "Abby", "age": 40, "email": "abby@gmail.com" }, { "id": 3, "name": "Gary", "age": 40, "email": "abby@gmail.com" } ] let newObj = { "id": 3, "name": "Gary", "age": 23, "email": "gary@gmail.com" } let foundOb = obj1.find(e => e.id === newObj.id); Object.assign(foundOb, newObj) console.log(obj1) 

you should normalize your data by id this way:

obj1 = {
   1: {
    "id": 1,
    "name": "Michel",
    "age": 34,
    "email": "michel@gmail.com"
  },
  2: {
    "id": 2,
    "name": "Abby",
    "age": 40,
    "email": "abby@gmail.com"
  },
  3: {
    "id": 3,
    "name": "Gary",
    "age": 40,
    "email": "abby@gmail.com"
  }
}

newObj = {
  3: {
    "id": 3,
    "name": "Gary",
    "age": 23,
    "email": "gary@gmail.com"
  }
}

this way you can use spread operator:

 { ...obj1, ...newObj }

in order to normalize you can use the reduce func this way:

const normalized = obj1.reduce((result, obj) => ({ ...result, [obj.id]: obj }), {})

You cannot use spread syntax in that way. One solution would be to find index of the object you want to replace by id property and then you could use spread syntax with slice method to create new array with replaced object.

 let obj1 = [{"id":1,"name":"Michel","age":34,"email":"michel@gmail.com"},{"id":2,"name":"Abby","age":40,"email":"abby@gmail.com"},{"id":3,"name":"Gary","age":40,"email":"abby@gmail.com"}] let newObj = {"id":3,"name":"Gary","age":23,"email":"gary@gmail.com"} const index = obj1.findIndex(({id}) => id == newObj.id) const result = [...obj1.slice(0, index), newObj, ...obj1.slice(index + 1)] console.log(result) 

I would do something like:

updatedObj = [obj1.map((entry) => entry.id !== newObj.id), newObj]

This would give me the updated object with minimal syntax

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM