Search code examples
javascriptrecursionlodash

Is it possible to update specific value of nested object with lodash?


I have a nested object like this

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["XXX"],
  type: "row"
};

I need to loop through all the children and update the path by appending an array of strings which is is const newPath = ["A", "B", "C"];

let newObj = cloneDeepWith(obj, (node) => {
  if (node.id) {
    node = { ...node, path: [...newPath, ...node.path] };
    console.log("updated : ", node)
  }
});

So final output of update object should be this

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["A", "B", "C", "XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["A", "B", "C", "XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["A", "B", "C", "XXX"],
  type: "row"
};

I'm trying to do it with cloneDeepWith function in lodash like this

let updatedObj = cloneDeepWith(obj, (node) => {
  if (node.id) {
    node = { ...node, path: [...newPath, ...node.path] };
    console.log("updated : ", node)
  }
});

In every console.log it prints the corrected updated node (in this case 3 with parent node) , but it doesn't return in updatedObj

How can I achieve this ?


Solution

  • I'm not sure how to do this is lodash, but doing in plain JS is pretty easy. Your recursion tag is the key..

    eg.

    let obj = {
      id: "XXX",
      children: [
        {
          id: "YYY",
          children: [],
          path: ["XXX", "YYY"],
          type: "text"
        },
        {
          id: "ZZZ",
          children: [],
          path: ["XXX", "ZZZ"],
          type: "button"
        }
      ],
      path: ["XXX"],
      type: "row"
    };
    
    function addABC(obj) {
      if (obj.path) obj.path = ['A','B','C',...obj.path];
      if (obj.children) for (const s of obj.children) addABC(s);
    }
    
    addABC(obj);
    
    console.log(obj);