ReactJS and Material UI TreeView: can I use a JSON/array of object to populate the TreeView? ReactJS and Material UI TreeView: can I use a JSON/array of object to populate the TreeView? json json

ReactJS and Material UI TreeView: can I use a JSON/array of object to populate the TreeView?


The TreeView component doesn't have anything built-in for this, but it is fairly straightforward to create re-usable code to provide this functionality for a given data structure.

Here is one way to do it:

import React from "react";import ReactDOM from "react-dom";import TreeView from "@material-ui/lab/TreeView";import TreeItem from "@material-ui/lab/TreeItem";import ExpandMoreIcon from "@material-ui/icons/ExpandMore";import ChevronRightIcon from "@material-ui/icons/ChevronRight";import { sampleFromStackOverflowQuestion, seasons } from "./sampleData";const getTreeItemsFromData = treeItems => {  return treeItems.map(treeItemData => {    let children = undefined;    if (treeItemData.children && treeItemData.children.length > 0) {      children = getTreeItemsFromData(treeItemData.children);    }    return (      <TreeItem        key={treeItemData.id}        nodeId={treeItemData.id}        label={treeItemData.name}        children={children}      />    );  });};const DataTreeView = ({ treeItems }) => {  return (    <TreeView      defaultCollapseIcon={<ExpandMoreIcon />}      defaultExpandIcon={<ChevronRightIcon />}    >      {getTreeItemsFromData(treeItems)}    </TreeView>  );};function App() {  return (    <div className="App">      <DataTreeView treeItems={sampleFromStackOverflowQuestion} />      <br />      <DataTreeView treeItems={seasons} />    </div>  );}const rootElement = document.getElementById("root");ReactDOM.render(<App />, rootElement);

Edit Data-driven TreeView

DataTreeView and getTreeItemsFromData could be moved into a separate file and then imported in order to reuse them in multiple components.

Here is a Typescript version:

import * as React from "react";import TreeView from "@material-ui/lab/TreeView";import TreeItem from "@material-ui/lab/TreeItem";import ExpandMoreIcon from "@material-ui/icons/ExpandMore";import ChevronRightIcon from "@material-ui/icons/ChevronRight";import {  sampleFromStackOverflowQuestion,  seasons,  TreeItemData} from "./sampleData";const getTreeItemsFromData = (treeItems: TreeItemData[]) => {  return treeItems.map(treeItemData => {    let children = undefined;    if (treeItemData.children && treeItemData.children.length > 0) {      children = getTreeItemsFromData(treeItemData.children);    }    return (      <TreeItem        key={treeItemData.id}        nodeId={treeItemData.id}        label={treeItemData.name}        children={children}      />    );  });};interface DataTreeViewProps {  treeItems: TreeItemData[];}function DataTreeView({ treeItems }: DataTreeViewProps) {  return (    <TreeView      defaultCollapseIcon={<ExpandMoreIcon />}      defaultExpandIcon={<ChevronRightIcon />}    >      {getTreeItemsFromData(treeItems)}    </TreeView>  );}export default function App() {  return (    <div className="App">      <DataTreeView treeItems={sampleFromStackOverflowQuestion} />      <br />      <DataTreeView treeItems={seasons} />    </div>  );}

Edit Typescript data-driven TreeView


Here is one more way to day as mentioned in the Material UI Docs.

import React from 'react';import { makeStyles } from '@material-ui/core/styles';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';import _ from 'lodash';const useStyles = makeStyles({  root: {    height: 216,    flexGrow: 1,    maxWidth: 400,  },});export default function ControlledTreeView(props) {  const classes = useStyles();  const [expanded, setExpanded] = React.useState([]);  const [selected, setSelected] = React.useState([]);  const [searchValue, setSearchValue] = React.useState('');  const [stateData, setStateData] = React.useState([]);  React.useEffect(    () => {      const { data } = props;      setStateData(data);    },    [props],  );  const handleToggle = (event, nodeIds) => {    setExpanded(nodeIds);  };  const handleSelect = (event, nodeIds) => {    setSelected(nodeIds);  };  const onSearch = (search) => {    setSearchValue(search);    console.log(searchTree(search, props.data));  };  function searchTree(str, data) {    const searchStr = str.toLowerCase();    // Only return the entries that contain a matched value    return _.filter(data, (datum) => {      // Check if name matches      return _.includes(datum.name, searchStr)      || _.some(datum.activities, (activity) => {          return _.entries(activity.routines).some(([routine, {details}]) => {            // Check if dynamic routine matches or details            return _.includes(routine, searchStr) || _.includes(details, searchStr);          });        });    });  };  const renderTree = (nodes) => (    <TreeItem key={nodes.id} nodeId={nodes.id} label={nodes.name}>      {Array.isArray(nodes.children) ? nodes.children.map((node) => renderTree(node)) : null}    </TreeItem>  );  return (    <div>      <TreeView        className={classes.root}        defaultCollapseIcon={<ExpandMoreIcon />}        defaultExpanded={['root']}        defaultExpandIcon={<ChevronRightIcon />}      >        {renderTree(stateData)}      </TreeView>    </div>  );}

And you can call this component as<CustomizedTreeView data={TreeViewData} />

where your TreeViewData will be

const TreeViewData = {  id: 'root',  name: 'Documents',  children: [    {      id: '1',      name: 'Report',      children: [        {          id: '2',          name: 'PDF',        },      ],    },    {      id: '3',      name: 'Files',      children: [        {          id: '4',          name: 'Excel',        },      ],    },    {      id: '5',      name: 'Programs',      children: [        {          id: '6',          name: 'Codes',        },        {          id: '7',          name: 'Data',        },      ],    },  ],};