Reputation: 66
I am having a problem trying to modify the name of a nested object using map function and to return the modified object.
I was trying the approach with double forEach loop but I am also failing with that.
const myObject = [{
id: 1,
childrenList: [{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'foo',
},
],
},
{
id: 2,
childrenList: [{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'foo',
},
],
},
];
const alteredObject = myObject.map((thisChild) => {
if (thisChild.id === 1) {
thisChild.childrenList.map((item) => {
if (item.id === 1) {
return {
...item,
name: 'bar',
};
}
return item;
});
}
return thisChild;
});
console.log(alteredObject);
//trying to get:
alteredObject = [
{
id: 1,
childrenList: [
{
id: 1,
name: 'bar',
},
{
id: 2,
name: 'foo',
},
],
},
{
id: 2,
childrenList: [
{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'foo',
},
],
},
];
This is the first time I am trying to modify a nested object. Normally with an array of objects, I am not having any issue so I am not sure what I am doing wrong
Upvotes: 1
Views: 354
Reputation: 24648
You're missing a return
; you have to return the modified thisChild
as {...thisChild, childrenList:modifiedChildrenList}
const myObject = [{ id: 1, childrenList: [{ id: 1, name: 'foo', }, { id: 2, name: 'foo', }, ], }, { id: 2, childrenList: [{ id: 1, name: 'foo', }, { id: 2, name: 'foo', }, ], }, ];
const alteredObject = myObject.map((thisChild) => {
if (thisChild.id === 1) {
return {...thisChild,childrenList:thisChild.childrenList.map((item) => {
if (item.id === 1) {
return {
...item,
name: 'bar',
};
}
return item;
})
}
}
return thisChild;
});
console.log(alteredObject);
Upvotes: 0
Reputation: 725
As you already know, Array.prototype.map()
returns a new Array containing the modified version.
In your first map function myObject.map()
, you aren't saving the second map function modified result as the childrenList
content.
therefore no changes would be stored in the first map function and the result would have no changes.
const alteredObject = myObject.map((thisChild) => {
if (thisChild.id === 1) {
// Here you should save the result of this
// Array.prototype.map() Function as the new 'thisChild.childrenList'
thisChild.childrenList = thisChild.childrenList.map((item) => {
// ...
});
}
return thisChild;
});
const myObject = [{
id: 1,
childrenList: [{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'foo',
},
],
},
{
id: 2,
childrenList: [{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'foo',
},
],
},
];
const alteredObject = myObject.map((thisChild) => {
if (thisChild.id === 1) {
thisChild.childrenList = thisChild.childrenList.map((item) => {
if (item.id === 1) {
return {
...item,
name: 'bar',
};
}
return item;
});
}
return thisChild;
});
console.log(alteredObject);
Upvotes: 1
Reputation: 2066
You only need to update the children with your map and it will work. Like this:
const myObject = [
{
id: 1,
childrenList: [
{
id: 1,
name: "foo"
},
{
id: 2,
name: "foo"
}
]
},
{
id: 2,
childrenList: [
{
id: 1,
name: "foo"
},
{
id: 2,
name: "foo"
}
]
}
];
const alteredObject = myObject.map((thisChild) => {
if (thisChild.id === 1) {
thisChild.childrenList = thisChild.childrenList.map((item) => {
if (item.id === 1) {
return {
...item,
name: "bar"
};
}
return item;
});
}
return thisChild;
});
console.log(alteredObject);
const myObject = [
{
id: 1,
childrenList: [
{
id: 1,
name: "foo"
},
{
id: 2,
name: "foo"
}
]
},
{
id: 2,
childrenList: [
{
id: 1,
name: "foo"
},
{
id: 2,
name: "foo"
}
]
}
];
const alteredObject = myObject.map((thisChild) => {
if (thisChild.id === 1) {
thisChild.childrenList.forEach((item) => {
if (item.id === 1) {
item.name = 'bar';
}
return item;
});
}
return thisChild;
});
console.log(alteredObject);
If you can modify your object then you can do it with two forEach:
const myObject = [
{
id: 1,
childrenList: [
{
id: 1,
name: "foo"
},
{
id: 2,
name: "foo"
}
]
},
{
id: 2,
childrenList: [
{
id: 1,
name: "foo"
},
{
id: 2,
name: "foo"
}
]
}
];
myObject.forEach((thisChild) => {
if (thisChild.id === 1) {
thisChild.childrenList.forEach((item) => {
if (item.id === 1) {
item.name = 'bar';
}
return item;
});
}
});
console.log(myObject);
Upvotes: 1
Reputation: 559
The array map
method creates a new array (mdn), so the parent object alteredObject
still has the childrenList
key pointing to the original array.
To solve this, you can add assignment of the new array to the key:
thisChild.childrenList = thisChild.childrenList.map(...)
This way, the key will point to the newly created array
Upvotes: 0
Reputation: 30725
This can be done with a couple of map calls, we'll alter the name
value if the firstChild id is 1 and the leaf object id is also 1:
const myObject = [ { id: 1, childrenList: [ { id: 1, name: 'foo', }, { id: 2, name: 'foo', }, ], }, { id: 2, childrenList: [ { id: 1, name: 'foo', }, { id: 2, name: 'foo', }, ], }, ];
const alteredObject = myObject.map((thisChild) => {
return { ...thisChild, childrenList: thisChild.childrenList.map(({id, name}) => {
return { id, name: (thisChild.id === 1 && id === 1) ? 'bar': name };
})}
});
console.log(alteredObject)
.as-console-wrapper { max-height: 100% !important; }
Upvotes: 0
Reputation: 1123
You can use this code :
const myObject = [
{
id: 1,
childrenList: [
{ id: 1, name: 'foo', },
{ id: 2, name: 'foo', },
],
},
{
id: 2,
childrenList: [
{ id: 1, name: 'foo', },
{ id: 2, name: 'foo', },
],
},
];
let result = myObject.map(
el => el.id === 1 ?
{...el, childrenList: el.childrenList.map(child => child.id === 1 ? {...child, name: 'bar'} : child)}
: el
);
console.log(result);
Upvotes: 0