1

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

6 Answers 6

1

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);
And if you want to do it with 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"
        }
      ]
    }
  ];

  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);

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

2 Comments

This is exactly what I needed, thanks. Just a question - isn't 2x forEach loop not recommended?
I added the solution with 2 forEachs but then you are modifying the original object.
1

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);

Comments

0

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);

Comments

0

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; }

Comments

0

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

Comments

0

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);

2 Comments

There is something missing: Result: [ [ { "id": 1, "name": "bar" }, { "id": 2, "name": "foo" } ], { "id": 2, "childrenList": [ { "id": 1, "name": "foo" }, { "id": 2, "name": "foo" } ] } is not equal to the one expected. Missing first parent object with id 1 in the array
You're quite right; it's fixed now.

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.