javascript - Material UI - TreeView 数据结构

标签 javascript reactjs material-ui

我想构建从服务器获取的数据,因此我可以使用 Material UI 中的 TreeView 组件:https://material-ui.com/api/tree-view/

我正在获取大量数据,因此我想在用户单击展开按钮时从服务器获取子节点。所以 当第一个节点展开时,一个 HTTP 请求被发送到服务器,该服务器返回该节点的所有子节点。当展开另一个节点时,会获取该节点的子节点等。

在页面启动时,我想获取根节点及其子节点。返回的 JSON 看起来像这样:

{
 "division": {
 "id": "1234",
 "name": "Teest",
 "address": "Oslo"
 },
 "children": [
   {
    "id": "3321",
    "parentId": "1234",
    "name": "Marketing",
    "address": "homestreet"
   },
   {
    "id": "3323",
    "parentId": "1234",
    "name": "Development",
    "address": "homestreet"
   }
 ]
}

展开 Marketing 节点时,我想进行 HTTP 调用以获取该节点的子节点。所以我会得到这样的 JSON:

{
  "children": [
    {
      "id": "2212",
      "parentId": "3321",
      "name": "R&D",
      "address": "homestreet"
    },
    {
      "id": "4212",
      "parentId": "3321",
      "name": "Testing",
      "address": "homestreet"
    }
  ]
}

但我对如何创建这样的数据结构感到困惑,该数据结构以后可以在我的 TreeView 组件中使用。如何创建这样的结构?

最佳答案

对于仍在寻找此问题解决方案的任何人,我最近使用 TreeView API 中的 selectedexpanded Prop 组合解决了这个问题。 .看这个Code Sandbox demo有关如何异步加载新子项并在加载后展开其父项的示例。

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";
import TreeNode from "./TreeNode";

const mockApiCall = async () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      const nextId = Math.ceil(Math.random() * 100);
      resolve([
        {
          id: `${nextId}`,
          name: `child-${nextId}`,
          children: []
        },
        {
          id: `${nextId + 1}`,
          name: `child-${nextId + 1}`,
          children: []
        }
      ]);
    }, Math.ceil(Math.random() * 1000));
  });
};

export default class Demo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: [],
      selected: "1",
      tree: new TreeNode({
        id: "1",
        name: "src",
        children: []
      })
    };
  }

  handleChange = async (event, nodeId) => {
    const node = this.state.tree.search(nodeId);
    if (node && !node.children.length) {
      mockApiCall()
        .then((result) => {
          this.setState({ tree: this.state.tree.addChildren(result, nodeId) });
        })
        .catch((err) => console.error(err))
        .finally(() => {
          this.setState({
            selected: nodeId,
            expanded: [...this.state.expanded, nodeId]
          });
        });
    }
  };

  createItemsFromTree = (tree) => {
    if (tree.children.length) {
      return (
        <TreeItem key={tree.id} nodeId={tree.id} label={tree.name}>
          {tree.children.length > 0 &&
            tree.children.map((child) => this.createItemsFromTree(child))}
        </TreeItem>
      );
    }
    return <TreeItem key={tree.id} nodeId={tree.id} label={tree.name} />;
  };

  render() {
    return (
      <TreeView
        defaultCollapseIcon={<ExpandMoreIcon />}
        defaultExpandIcon={<ChevronRightIcon />}
        selected={this.state.selected}
        onNodeSelect={this.handleChange}
        expanded={this.state.expanded}
      >
        {this.createItemsFromTree(this.state.tree)}
      </TreeView>
    );
  }
}

关于javascript - Material UI - TreeView 数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59452799/

相关文章:

reactjs - 大量使用本地存储是一种好的做法吗?

javascript - React material-ui withStyles 对外部文件不起作用

javascript - 如何删除 TextField 状态

javascript - "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received",这是什么意思?

javascript - 回流 Action 触发两次

javascript - 一个 Javascript 计算器代码

javascript - Array.prototype.reduce() 在一个元素的数组上

javascript - Material UI 多选 |如何对数组使用多重选择

javascript - JS 和 Vue.js 中的动态导入

javascript - 从与图表无关的事件中获取当前选择的rangeSelector