I have the below code:
<TreeView
aria-label="controlled"
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronLeftIcon />}
expanded={expanded}
selected={selected}
onNodeToggle={handleToggle}
onNodeSelect={handleSelect}
multiSelect
>
{
rows.data.map((item: IPTreeModel)=> {
return (
<TreeItem nodeId={item.id} label={item.subnet} onClick={item.has_child ? (e: MouseEvent)=> loadChildren(e, item.subnet) : ()=> ''}>
{/*here*/}
</TreeItem>
)
})
}
</TreeView>
And below is my function:
const loadChildren = (e: MouseEvent, id: number | string) => {
// fetch new data based on the ID parameter, and append the output as a TreeItem element.
}
Now I need to append a new <TreeItem> element to the last <TreeItem> in case user clicks on loadChildren function.
How is the react way of doing this?
Add a new field to your rows.data object and make sure to store it as a state.
do this by cloning your previous array, doing a pushback and then setting a new state with your new modified array.
This will trigger the redraw of the TreeView component.
Edit 1:
Here's a quick example of how you could do this. Have an onClick call the addData function to add data to your structure.
const [data, setData] = useState([]);
const addData = () => {
const tmp = data.slice();
tmp.push([new data]);
setData(tmp);
}
return (
<div className="App">
<TreeView>
{data.map((item) => {
<TreeItem data={item} ></TreeItem>
})}
</TreeView>
</div>
);
I ended up resolving the issue like below:
const loadChildren = (e: any, id: number | string) => {
setLoadingChildren(true)
getIpState(id).then(res=> {
setRows({
...rows,
data: rows.data.map((item: any) => item.id == id ? {...item, child: res.data} : item)
})
setLoadingChildren(false)
}).catch(err => {
console.log(err)
setLoadingChildren(false)
})
}
const traverse = (o: any) => {
if (!loadingChildren){
return o.map((item: any, key: number) => {
let extra = item.hasOwnProperty('extra') ? item.extra : item
return (
<TreeItem key={key} nodeId={extra.id} icon={item.has_child ? <ChevronLeftIcon /> : ''} label={item.subnet} onClick={extra.has_child ? (e)=> loadChildren(e, extra.id) : ()=> ''}>
{item.child ? traverse(item.child) : ''}
</TreeItem>
)
}
)
}
}
And display the output like:
<TreeView
aria-label="controlled"
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronLeftIcon />}
expanded={expanded}
selected={selected}
onNodeToggle={handleToggle}
onNodeSelect={handleSelect}
multiSelect
>
{traverse(rows.data)}
</TreeView>