React.js中MUI Tree View因节点ID重复报错求助
解决MUI X TreeView重复id错误问题
问题原因
你使用的MUI X TreeView v6+版本调整了API规范:原有的TreeView组件改为无头组件,不再支持直接嵌套TreeItem的写法,必须使用SimpleTreeView(基础树形视图)或RichTreeView(增强版)来实现嵌套结构;否则会触发id未定义/重复的错误。
修复方案
方案1:切换到SimpleTreeView组件(适配原有嵌套写法)
修改TreeHierarchy.js中的导入和组件使用,同时优化id生成逻辑:
import React from "react"; // 替换原有TreeView为SimpleTreeView import { SimpleTreeView, TreeItem } from "@mui/x-tree-view"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; // Sample hierarchy const hierarchy = { name: "Bahria", precincts: [ { name: "Precinct-1", streets: [ { name: "Road 1", meters: ["3092000001", "3092000210"], }, { name: "Street 21", meters: ["3092000012"], }, ], }, ], }; // 递归渲染树形结构,优化id生成 const TreeHierarchy = () => { const renderTree = (node, parentId = "root") => { // 用root作为初始父id,避免id以横杠开头 const nodeId = `${parentId}-${node.name}`; return ( <TreeItem key={nodeId} nodeId={nodeId} label={node.name}> {/* 调整顺序,先渲染precincts再渲染streets,匹配期望结构 */} {node.precincts && node.precincts.map((precinct, index) => renderTree(precinct, `${nodeId}-precinct-${index}`) )} {node.streets && node.streets.map((street, index) => renderTree(street, `${nodeId}-street-${index}`) )} {node.meters && node.meters.map((meter, index) => ( <TreeItem key={`${nodeId}-meter-${index}`} nodeId={`${nodeId}-meter-${index}`} label={`Meter: ${meter}`} /> ))} </TreeItem> ); }; return ( <SimpleTreeView defaultCollapseIcon={<ExpandMoreIcon />} defaultExpandIcon={<ChevronRightIcon />} > {renderTree(hierarchy)} </SimpleTreeView> ); }; export default TreeHierarchy;
方案2:改用声明式items prop写法(v6+推荐用法)
如果你想遵循MUI X v6的最佳实践,可以将嵌套数据转换为扁平结构,配合items和getItemId prop实现:
import React from "react"; import { TreeView } from "@mui/x-tree-view"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; // 将嵌套层级数据转换为扁平items结构 const flattenHierarchy = (node, parentId = null, items = []) => { const itemId = node.name; items.push({ id: itemId, label: node.name, parentId: parentId, }); // 递归处理子节点 if (node.precincts) { node.precincts.forEach(precinct => flattenHierarchy(precinct, itemId, items)); } if (node.streets) { node.streets.forEach(street => flattenHierarchy(street, itemId, items)); } if (node.meters) { node.meters.forEach(meter => { items.push({ id: `meter-${meter}`, label: `Meter: ${meter}`, parentId: itemId, }); }); } return items; }; const hierarchy = { name: "Bahria", precincts: [ { name: "Precinct-1", streets: [ { name: "Road 1", meters: ["3092000001", "3092000210"], }, { name: "Street 21", meters: ["3092000012"], }, ], }, ], }; const TreeHierarchy = () => { const items = flattenHierarchy(hierarchy); return ( <TreeView items={items} defaultCollapseIcon={<ExpandMoreIcon />} defaultExpandIcon={<ChevronRightIcon />} getItemId={(item) => item.id} /> ); }; export default TreeHierarchy;
最终效果
修复后会按照你的期望渲染树形结构:
Bahria => Precinct-1 => Road 1 => Meter: 3092000001 => Meter: 3092000210 => Street 21 => Meter: 3092000012
内容的提问来源于stack exchange,提问作者Moeez
相关产品推荐
相关产品推荐

