You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改React代码生成合规的无键名嵌套侧边栏结构?

问题

需要从指定路径(示例:/docs/quick-start/messaging/Virtual-Numbers/digital/)生成用于侧边栏的嵌套文件夹结构,目前已实现功能但结果不符合预期。当前代码生成的是带键名的嵌套对象结构,想要生成以children数组存储子节点的层级结构。以下是相关代码、当前输出及合规的期望结构,请问如何修改代码?

原代码片段

export function useSideNavState() {
  const data = useStaticQuery(SideNavQuery)
  const tree = {}

  //Working Code
  newGroups.forEach(({ name: topNodeName, nodes }) => {
    let currentNode = tree

    nodes.forEach(({ fields }) => {
      const { slug, nodeName } = fields
      // /docs/quick-start/messaging/Virtual-Numbers/digital/
      let parts = slug.split('/')
      parts = parts.filter((element) => {
        return element !== ''
      })
      const lastPart = parts[parts.length - 2]

      parts.forEach((part, index) => {
        if (part === '') return
        currentNode[part] = currentNode[part] ?? {}
        currentNode[part].name = currentNode[part].name ?? part
        currentNode = currentNode[part]
        if (index === parts.length - 2) {
          currentNode.name = nodeName ?? lastPart
        }
      })

      if (!currentNode.items) currentNode.items = []
      currentNode.items.push(fields)
      currentNode = tree
    })

    if (!tree[topNodeName]) tree[topNodeName] = {}
    tree[topNodeName][topNodeName] = {
      ...currentNode[topNodeName],
      name: topNodeName,
    }
    addNameProperty(tree[topNodeName])
  })

  // helper function to add name property recursively
  function addNameProperty(obj) {
    for (const key in obj) {
      if (typeof obj[key] === 'object') {
        obj[key].name = obj[key].name ?? key
        addNameProperty(obj[key])
      }
    }
  }

  console.log(tree)
  return newGroups
})
// console.log(navGroups)
return { navGroups }
}

当前输出

{
"name": "docs",
"quick-start": {
    "name": "quick-start",
    "messaging": {
        "name": "messaging",
        "items": [
            {
                "title": "Messaging",
                "pageType": "doc",
                "section": "messaging",
                "order": 1,
                "slug": "/docs/quick-start/messaging/"
            }
        ],
        "Virtual-Numbers": {
            "name": "Virtual-Numbers",
            "digital": {
                "name": "digital",
                "items": [
                    {
                        "title": "digital",
                        "pageType": "doc",
                        "section": "messaging",
                        "order": -9999,
                        "slug": "/docs/quick-start/messaging/Virtual-Numbers/digital/"
                    }
                ]
            },
            "items": [
                {
                    "title": "EnableX Virtual Numbers",
                    "pageType": "doc",
                    "section": "messaging",
                    "order": -9999,
                    "slug": "/docs/quick-start/messaging/Virtual-Numbers"
                }
            ]
        }
    }
}
}

期望输出(合规格式)

{
"name": "docs",
"children": [
    {
        "name": "quick-start",
        "children": [
            {
                "name": "messaging",
                "items": [
                    {
                        "title": "Messaging",
                        "pageType": "doc",
                        "section": "messaging",
                        "order": 1,
                        "slug": "/docs/quick-start/messaging/"
                    }
                ],
                "children": [
                    {
                        "name": "Virtual-Numbers",
                        "children": [
                            {
                                "name": "digital",
                                "items": [
                                    {
                                        "title": "digital",
                                        "pageType": "doc",
                                        "section": "messaging",
                                        "order": -9999,
                                        "slug": "/docs/quick-start/messaging/Virtual-Numbers/digital/"
                                    }
                                ]
                            }
                        ],
                        "items": [
                            {
                                "title": "EnableX Virtual Numbers",
                                "pageType": "doc",
                                "section": "messaging",
                                "order": -9999,
                                "slug": "/docs/quick-start/messaging/Virtual-Numbers"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]
}
解决方案

核心改动是把原有的键值对嵌套对象改成**children数组存储子节点**的结构,具体修改如下:

修改后的完整代码

export function useSideNavState() {
  const data = useStaticQuery(SideNavQuery)
  // 初始化根节点,包含name和children数组
  const tree = { name: "docs", children: [] };

  newGroups.forEach(({ name: topNodeName, nodes }) => {
    let currentNode = tree;

    nodes.forEach(({ fields }) => {
      const { slug, nodeName } = fields;
      // 拆分路径并过滤空片段,移除末尾的空项(因路径带/)
      let parts = slug.split("/").filter(element => element !== "");
      parts = parts.slice(0, -1);
      const lastPart = parts[parts.length - 1];

      parts.forEach((part, index) => {
        // 在当前节点的children中查找已存在的节点
        let existingNode = currentNode.children.find(child => child.name === part);
        if (!existingNode) {
          // 不存在则创建新节点,包含name和空children数组
          existingNode = { name: part, children: [] };
          currentNode.children.push(existingNode);
        }
        currentNode = existingNode;
        // 若为最后一个层级,替换为nodeName(如果有)
        if (index === parts.length - 1) {
          currentNode.name = nodeName ?? lastPart;
        }
      });

      // 为当前节点添加items数组并推入字段
      if (!currentNode.items) currentNode.items = [];
      currentNode.items.push(fields);
      // 重置回根节点
      currentNode = tree;
    });
  });

  console.log(tree);
  // 返回处理后的树结构
  return { navGroups: tree };
}

关键改动说明

  1. 根节点初始化:直接定义符合期望结构的根节点,包含name和空children数组
  2. 节点查找与创建:遍历路径片段时,通过children.find匹配已存在的子节点,不存在则创建新节点并推入数组
  3. 命名逻辑保留:保持原有的nodeName优先级,无nodeName时使用路径片段名称
  4. 移除冗余函数:删除原addNameProperty辅助函数,节点创建时已直接设置name属性

内容的提问来源于stack exchange,提问作者Guru Pawar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 06:53:10