I am trying to create a treeview in React.js. But I am not able to set it properly. Below is my code
App.js
import React from "react";
import TreeHierarchy from "./TreeHierarchy"; // Adjust path if necessary
const App = () => {
return (
<div style={{ padding: "20px" }}>
<h1>Bahria Hierarchy</h1>
<TreeHierarchy />
</div>
);
};
export default App;
TreeHierarchy.js
import React from "react";
import { TreeView, 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"],
},
],
},
],
};
// Recursive function to render the hierarchy tree
const TreeHierarchy = () => {
const renderTree = (node, parentId = "") => {
const nodeId = `${parentId}-${node.name || "node"}`;
return (
<TreeItem key={nodeId} nodeId={nodeId} label={node.name || "Unnamed"}>
{node.streets &&
node.streets.map((street, index) =>
renderTree(street, `${nodeId}-street-${index}`)
)}
{node.precincts &&
node.precincts.map((precinct, index) =>
renderTree(precinct, `${nodeId}-precinct-${index}`)
)}
{node.meters &&
node.meters.map((meter, index) => (
<TreeItem
key={`${nodeId}-meter-${index}`}
nodeId={`${nodeId}-meter-${index}`}
label={`Meter: ${meter}`}
/>
))}
</TreeItem>
);
};
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
>
{renderTree(hierarchy)}
</TreeView>
);
};
export default TreeHierarchy;
Output
When I click on the main node name I am getting below errors
MUI X: The Tree View component requires all items to have a unique `id` property.
Alternatively, you can use the `getItemId` prop to specify a custom id for each item.
Two items were provided with the same id in the `items` prop: "undefined"
Error: MUI X: The Tree View component requires all items to have a unique `id` property.
Alternatively, you can use the `getItemId` prop to specify a custom id for each item.
Two items were provided with the same id in the `items` prop: "undefined"
at http://localhost:3000/static/js/bundle.js:15169:15
at basicStateReducer (http://localhost:3000/static/js/bundle.js:37272:45)
at updateReducer (http://localhost:3000/static/js/bundle.js:37381:26)
at updateState (http://localhost:3000/static/js/bundle.js:37667:14)
at Object.useState (http://localhost:3000/static/js/bundle.js:38464:20)
at Object.useState (http://localhost:3000/static/js/bundle.js:54836:25)
at useTreeView (http://localhost:3000/static/js/bundle.js:16177:64)
at SimpleTreeView (http://localhost:3000/static/js/bundle.js:12473:83)
at renderWithHooks (http://localhost:3000/static/js/bundle.js:37072:22)
at updateForwardRef (http://localhost:3000/static/js/bundle.js:40321:24)
The tree structure is below
Bharia (Parent node)
=> Precinct (value)
=>streets (value)
=> meters (value)
I am stuck to it and must be missing something. Any help would be highly appreciated.
TreeItem
needs a unique itemId
... as stated in the documentation.
This is the changed renderTree
function that respects this requirement:
const renderTree = (node, parentId = "") => {
const nodeId = `${parentId}-${node.name || "node"}`;
return (
<TreeItem
key={nodeId}
// itemId added here
itemId={nodeId}
nodeId={nodeId}
label={node.name || "Unnamed"}
>
{node.streets &&
node.streets.map((street, index) =>
renderTree(street, `${nodeId}-street-${index}`)
)}
{node.precincts &&
node.precincts.map((precinct, index) =>
renderTree(precinct, `${nodeId}-precinct-${index}`)
)}
{node.meters &&
node.meters.map((meter, index) => {
// an `id` constant to avoid repeating code
const id = `${nodeId}-meter-${index}`;
return (
<TreeItem
key={id}
// ...and another itemId here
itemId={id}
nodeId={`${nodeId}-meter-${index}`}
label={`Meter: ${meter}`}
/>
);
})}
</TreeItem>
);
};
In the code above, I've added a unique itemId
property to each TreeItem
.
I've also added an id
constant in your node.meters.map(...)
function argument, to avoid repeating the template string literal.