skip to Main Content

I’m trying to add a new element to the tree by id. I’m using recursion for this. My attempt

const treeData = [{
  title: 'parent 1',
  key: '0-0',
  children: [{
    title: 'parent 1-0',
    key: '0-0-0',
    disabled: true,
    children: [{
        title: 'leafffff',
        key: '0-0-0-0',
      }
    ],
  }, ],
}, ];

const recursiveUpdate = (data, key) => {
  return data.reduce((acc, el) => {
    if (el.key === key) {
      acc.push({
        ...el,
        children: [
          ...el.children || [],
          {
            title: '111111111111',
            key: 'new-key'
          },
        ],
      });
    } else if (el.children) {
      recursiveUpdate(el.children, key);
    }
    return acc;
  }, []);
}

console.log(recursiveUpdate(treeData, '0-0-0'));

This function only works at the nesting level. Help me with this problem

2

Answers


  1. Can you test using this code

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Test</title>
      </head>
      <body>
        <!-- Define the tree data -->
        <script>
          const treeData = [
            {
              title: "parent 1",
              key: "0-0",
              children: [
                {
                  title: "parent 1-0",
                  key: "0-0-0",
                  disabled: true,
                  children: [
                    {
                      title: "leafffff",
                      key: "0-0-0-0",
                    },
                  ],
                },
              ],
            },
          ];
        </script>
    
        <!-- Call the function -->
        <script>
          const recursiveUpdate = (data, key) => {
            return data.reduce((acc, el) => {
              if (el.key === key) {
                acc.push({
                  ...el,
                  children: [
                    ...(el.children || []),
                    {
                      title: "111111111111",
                      key: "new-key",
                    },
                  ],
                });
              } else if (el.children) {
                const updatedChildren = recursiveUpdate(el.children, key);
                if (updatedChildren.length > 0) {
                  acc.push({
                    ...el,
                    children: updatedChildren,
                  });
                }
              }
              return acc;
            }, []);
          };
    
          // Call the function with treeData and the target key
          const updatedTreeData = recursiveUpdate(treeData, "0-0-0");
          console.log(updatedTreeData);
        </script>
      </body>
    </html>
    Login or Signup to reply.
  2. You should add your non-matched elements too:

    const treeData = [{
        title: 'parent 1',
        key: '0-0',
        children: [{
            title: 'parent 1-0',
            key: '0-0-0',
            disabled: true,
            children: [{
                title: 'leafffff',
                key: '0-0-0-0',
            }
            ],
        },],
    },];
    
    const recursiveUpdate = (data, key) => {
        return data.reduce((acc, el) => {
            if (el.key === key) {
                acc.push({
                    ...el,
                    children: [
                        ...el.children || [],
                        {
                            title: '111111111111',
                            key: 'new-key'
                        },
                    ],
                });
            } else {
                acc.push({
                    ...el,
                    ...el.children ? { children: recursiveUpdate(el.children, key) } : {}
                });
            }
            return acc;
        }, []);
    }
    
    console.log(recursiveUpdate(treeData, '0-0-0'));

    Btw you don’t need Array:reduce() here. The Array:map() is enough and it’s faster:

    const treeData = [{
        title: 'parent 1',
        key: '0-0',
        children: [{
            title: 'parent 1-0',
            key: '0-0-0',
            disabled: true,
            children: [{
                title: 'leafffff',
                key: '0-0-0-0'
            }],
        },],
    },];
    
    const recursiveUpdate = (data, key) => data.map(el => ({
        ...el,
        ...el.key === key ? {
            children: [...el.children || [],
            {
                title: '111111111111',
                key: 'new-key'
            },
            ]
        } : el.children ? { children: recursiveUpdate(el.children, key) } : {},
    }));
    
    console.log(recursiveUpdate(treeData, '0-0-0'));

    But the problem is the OP commented that he/she wants to MODIFY the existing data though his code definitely creates a copy. So for modifying the existing data, we could just find a needed node to modify and add an extra child:

    const treeData = [{
        title: 'parent 1',
        key: '0-0',
        children: [{
            title: 'parent 1-0',
            key: '0-0-0',
            disabled: true,
            children: [{
                title: 'leafffff',
                key: '0-0-0-0',
            }
            ],
        },],
    },];
    
    const findNode = (node, key) => {
        if (Array.isArray(node)) {
          node = {children: node};
        }else if (node.key === key) {
            return node;
        }
        for (const child of node.children || []) {
            const found = findNode(child, key);
            if (found) return found;
        }
    };
    
    const node = findNode(treeData, '0-0-0');
    (node.children ??= []).push({
        title: '111111111111',
        key: 'new-key'
    });
    
    console.log(treeData);

    And a benchmark of map vs reduce:

    enter image description here

    <body></body>
    <script benchmark data-count="1000000">
    
        const treeData = [{
            title: 'parent 1',
            key: '0-0',
            children: [{
                title: 'parent 1-0',
                key: '0-0-0',
                disabled: true,
                children: [{
                    title: 'leafffff',
                    key: '0-0-0-0',
                    children: [{
                        title: 'some leaf',
                        key: '0-0-0-0-0'
                    }]
                }],
            },],
        },];
    
        // @benchmark reduce
        const recursiveUpdate = (data, key) => {
            return data.reduce((acc, el) => {
                if (el.key === key) {
                    acc.push({
                        ...el,
                        children: [
                            ...el.children || [],
                            {
                                title: '111111111111',
                                key: 'new-key'
                            },
                        ],
                    });
                } else {
                    acc.push({
                        ...el,
                        ...el.children ? { children: recursiveUpdate(el.children, key) } : {}
                    });
                }
                return acc;
            }, []);
        }
    
        // @run
        recursiveUpdate(treeData, '0-0-0');
    
        // @benchmark Alexander's map
        const recursiveUpdate2 = (data, key) => data.map(el => ({
            ...el,
            ...el.key === key ? {
                children: [...el.children || [],
                {
                    title: '111111111111',
                    key: 'new-key'
                },
                ]
            } : el.children ? { children: recursiveUpdate(el.children, key) } : {},
        }));
        
        // @run
        recursiveUpdate2(treeData, '0-0-0');
    
    </script>
    <script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search