为Ant Design树形表格数据的父级与子级添加唯一key并简化代码
问题描述
我已经把API返回的数据转换为适配Ant Design树形表格的格式,但目前遇到新问题:需要为每个父级和子级节点添加唯一的key,否则树形表格在展开/折叠时会重复生成行(注:只要key在所有父级和子级中唯一即可)。
恳请指导如何为父级和子级节点添加key,若能同时简化当前冗长的数据转换代码则更为感激。
当前数据转换代码
//api called data let apiData = [ { email: "alyssayo@xxx.com", permissionIds: null, roleIds: ["raa", "baa", "caa"], projectIds: ["1aa", "3aa"] }, { email: "chiuewww@xxx.com", permissionIds: null, roleIds: ["baa", "caa"], projectIds: ["1aa", "2aa", "3aa"] }, { email: "lalaqq@xxx.com", permissionIds: null, roleIds: ["caa"], projectIds: ["1aa"] } ]; //isolate and transform data const data = apiData.reduce((arr, item) => { console.log("~~~arr",JSON.stringify(arr)); console.log("~~~item",JSON.stringify(item)); let formatted = item.projectIds.map((id) => { return { projectIds: id, children: [{ ...item, projectIds: id }] }; }); console.log("~~~formatted",JSON.stringify(formatted)); console.log("arr Formtd", [...arr, ...formatted]); return [...arr, ...formatted]; }, []); //Function to group the data const findMatch = (arr, projectIds) => arr.find(item => item.projectIds === projectIds) const grouppingArray = (originalArr) => { return Array.isArray(originalArr) ? originalArr.reduce((previousObj, obj) => { if (findMatch(previousObj, obj.projectIds)) { findMatch(previousObj, obj.projectIds).children.push(...obj.children) } else { previousObj.push(obj) } return previousObj }, []) : 'Need an array' } console.log("FINALLL",JSON.stringify(grouppingArray(data)));
转换后的数据
[ { "projectIds": "1aa", "children": [ { "email": "alyssayo@xxx.com", "permissionIds": null, "roleIds": [ "raa", "baa", "caa" ], "projectIds": "1aa" }, { "email": "chiuewww@xxx.com", "permissionIds": null, "roleIds": [ "baa", "caa" ], "projectIds": "1aa" }, { "email": "lalaqq@xxx.com", "permissionIds": null, "roleIds": [ "caa" ], "projectIds": "1aa" } ] }, { "projectIds": "3aa", "children": [ { "email": "alyssayo@xxx.com", "permissionIds": null, "roleIds": [ "raa", "baa", "caa" ], "projectIds": "3aa" }, { "email": "chiuewww@xxx.com", "permissionIds": null, "roleIds": [ "baa", "caa" ], "projectIds": "3aa" } ] }, { "projectIds": "2aa", "children": [ { "email": "chiuewww@xxx.com", "permissionIds": null, "roleIds": [ "baa", "caa" ], "projectIds": "2aa" } ] } ]
期望结果
[ { "key": 1, "projectIds": "1aa", "children": [ { "key": 2, "email": "alyssayo@xxx.com", "permissionIds": null, "roleIds": [ "raa", "baa", "caa" ], "projectIds": "1aa" }, { "key": 3, "email": "chiuewww@xxx.com", "permissionIds": null, "roleIds": [ "baa", "caa" ], "projectIds": "1aa" }, { "key": 4, "email": "lalaqq@xxx.com", "permissionIds": null, "roleIds": [ "caa" ], "projectIds": "1aa" } ] }, { "key": 5, "projectIds": "3aa", "children": [ { "key": 6, "email": "alyssayo@xxx.com", "permissionIds": null, "roleIds": [ "raa", "baa", "caa" ], "projectIds": "3aa" }, { "key": 7, "email": "chiuewww@xxx.com", "permissionIds": null, "roleIds": [ "baa", "caa" ], "projectIds": "3aa" } ] }, { "key": 8, "projectIds": "2aa", "children": [ { "key": 9, "email": "chiuewww@xxx.com", "permissionIds": null, "roleIds": [ "baa", "caa" ], "projectIds": "2aa" } ] } ]
解决方案
可以通过先按projectId分组,再统一生成唯一key的方式实现,既简化代码逻辑,又保证key全局唯一:
let apiData = [ { email: "alyssayo@xxx.com", permissionIds: null, roleIds: ["raa", "baa", "caa"], projectIds: ["1aa", "3aa"] }, { email: "chiuewww@xxx.com", permissionIds: null, roleIds: ["baa", "caa"], projectIds: ["1aa", "2aa", "3aa"] }, { email: "lalaqq@xxx.com", permissionIds: null, roleIds: ["caa"], projectIds: ["1aa"] } ]; // 第一步:按projectId分组,构建树形结构雏形 const projectGroups = apiData.reduce((groups, user) => { user.projectIds.forEach(projectId => { if (!groups[projectId]) groups[projectId] = []; groups[projectId].push({ ...user, projectIds: projectId }); }); return groups; }, {}); // 第二步:生成带唯一key的最终树形数据 let keyCounter = 1; const finalTreeData = Object.entries(projectGroups).map(([projectId, children]) => { const parentKey = keyCounter++; const childrenWithKeys = children.map(child => ({ ...child, key: keyCounter++ })); return { key: parentKey, projectIds: projectId, children: childrenWithKeys }; }); console.log(JSON.stringify(finalTreeData, null, 2));
代码说明
- 简化分组逻辑:直接用对象按
projectId分组,避免原代码中拆分再合并的冗余步骤,执行效率更高。 - 全局唯一key:通过计数器
keyCounter依次给父节点、子节点分配key,确保所有节点的key不重复。 - 逻辑清晰:分两步完成转换,先处理数据分组,再添加key,代码结构简洁易维护。
内容的提问来源于stack exchange,提问作者Jing c
相关产品推荐
相关产品推荐

