I'm building a TreeView
with the Treeview ponent from Material UI: /
I have created the ponent below which fetches data when a node is expanded. Furthermore, the tree is build so each node that have children also is a tree, but I have two questions:
Question 1:
Right now the fetchChildNodes
gets called each time a node is expanded. I want to change this so that i'm checking if the current node has been expanded before. If it has been expanded I don't want to call fetchChildNodes
, but use the data fetched earlier. This is because I for a node can expand, close, and expand again, and the fetchChildNodes
will in this process be called twice. How can I check this?
Question 2:
Is there some kind of onClick
method that can provide the nodeId
for the node clicked? The expandingNodes
only provides nodeId
for expandable nodes and not leaf
nodes.
import ReactDOM from "react-dom";
import React from "react";
import TreeView from "@material-ui/lab/TreeView";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import TreeItem from "@material-ui/lab/TreeItem";
const { useState, useCallback } = React;
export default function MyTreeItem(props) {
const [childNodes, setChildNodes] = useState(null);
const [expanded, setExpanded] = React.useState([]);
function fetchChildNodes(id) {
return new Promise(resolve => {
setTimeout(() => {
resolve({
children: [
{
id: "2",
name: "Calendar"
},
{
id: "3",
name: "Settings"
},
{
id: "4",
name: "Music"
}
]
});
}, 1000);
});
}
const handleChange = (event, nodes) => {
const expandingNodes = nodes.filter(x => !expanded.includes(x));
setExpanded(nodes);
if (expandingNodes[0]) {
const childId = expandingNodes[0];
fetchChildNodes(childId).then(result =>
setChildNodes(
result.children.map(node => <MyTreeItem key={node.id} {...node} />)
)
);
}
};
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
expanded={expanded}
onNodeToggle={handleChange}
>
{/*The node below should act as the root node for now */}
<TreeItem nodeId={props.id} label={props.name}>
{childNodes || [<div key="stub" />]}
</TreeItem>
</TreeView>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MyTreeItem id="1" name="Applications" />, rootElement);
I'm building a TreeView
with the Treeview ponent from Material UI: https://material-ui./ponents/tree-view/
I have created the ponent below which fetches data when a node is expanded. Furthermore, the tree is build so each node that have children also is a tree, but I have two questions:
Question 1:
Right now the fetchChildNodes
gets called each time a node is expanded. I want to change this so that i'm checking if the current node has been expanded before. If it has been expanded I don't want to call fetchChildNodes
, but use the data fetched earlier. This is because I for a node can expand, close, and expand again, and the fetchChildNodes
will in this process be called twice. How can I check this?
Question 2:
Is there some kind of onClick
method that can provide the nodeId
for the node clicked? The expandingNodes
only provides nodeId
for expandable nodes and not leaf
nodes.
import ReactDOM from "react-dom";
import React from "react";
import TreeView from "@material-ui/lab/TreeView";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import TreeItem from "@material-ui/lab/TreeItem";
const { useState, useCallback } = React;
export default function MyTreeItem(props) {
const [childNodes, setChildNodes] = useState(null);
const [expanded, setExpanded] = React.useState([]);
function fetchChildNodes(id) {
return new Promise(resolve => {
setTimeout(() => {
resolve({
children: [
{
id: "2",
name: "Calendar"
},
{
id: "3",
name: "Settings"
},
{
id: "4",
name: "Music"
}
]
});
}, 1000);
});
}
const handleChange = (event, nodes) => {
const expandingNodes = nodes.filter(x => !expanded.includes(x));
setExpanded(nodes);
if (expandingNodes[0]) {
const childId = expandingNodes[0];
fetchChildNodes(childId).then(result =>
setChildNodes(
result.children.map(node => <MyTreeItem key={node.id} {...node} />)
)
);
}
};
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
expanded={expanded}
onNodeToggle={handleChange}
>
{/*The node below should act as the root node for now */}
<TreeItem nodeId={props.id} label={props.name}>
{childNodes || [<div key="stub" />]}
</TreeItem>
</TreeView>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MyTreeItem id="1" name="Applications" />, rootElement);
Share
Improve this question
asked Dec 26, 2019 at 16:27
JohnJohn
4372 gold badges8 silver badges23 bronze badges
1
- check this: github./mui-org/material-ui/issues/… – Inzamam Malik Commented Nov 17, 2020 at 17:19
2 Answers
Reset to default 5Answering Question 2:
just add custom label object to TreeItem :
import ReactDOM from "react-dom";
import React from "react";
import TreeView from "@material-ui/lab/TreeView";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import TreeItem from "@material-ui/lab/TreeItem";
const { useState, useCallback } = React;
export default function MyTreeItem(props) {
const [childNodes, setChildNodes] = useState(null);
const [expanded, setExpanded] = React.useState([]);
function fetchChildNodes(id) {
return new Promise(resolve => {
setTimeout(() => {
resolve({
children: [
{
id: "2",
name: "Calendar"
},
{
id: "3",
name: "Settings"
},
{
id: "4",
name: "Music"
}
]
});
}, 1000);
});
}
const handleChange = (event, nodes) => {
const expandingNodes = nodes.filter(x => !expanded.includes(x));
setExpanded(nodes);
if (expandingNodes[0]) {
const childId = expandingNodes[0];
fetchChildNodes(childId).then(result =>
setChildNodes(
result.children.map(node => (
<MyTreeItem key={node.id} {...node} />
))
)
);
}
};
const renderLabel = item => (
<span
onClick={event => {
console.log(item.id);
//setActiveItemId(item.id);
// if you want after click do expand/collapse ment this two line
event.stopPropagation();
event.preventDefault();
}}
>
{item.name}
</span>
);
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
expanded={expanded}
onNodeToggle={handleChange}
>
{/*The node below should act as the root node for now */}
<TreeItem nodeId={props.id} label={renderLabel(props)}>
{childNodes || [<div key="stub" />]}
</TreeItem>
</TreeView>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<MyTreeItem id="1" name="Applications" />,
rootElement
);
Question2 Answer: You can use onNodeSelect={action}
on TreeView
and action can be something like below
function action(event, nodeId) {
console.log('nodeId: ', nodeId)
}