提取异步TreeView数据

时间:2019-12-25 18:00:52

标签: javascript reactjs

我是新来的响应者,我正在构建一个TreeView组件以在React中扩展节点时获取数据。我正在从Material UI中使用TreeView:https://material-ui.com/api/tree-view/

我创建了一个组件,当扩展节点时,该组件在其下方获取数据。 MyTreeItem是一个自定义版本,可通过fetch调用扩展原始版本。但是我对如何显示子节点感到困惑。我怎样才能做到这一点?

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({ id, name }) {
  const [childNodes, setChildNodes] = useState(null);
  const [expanded, setExpanded] = React.useState([]);

  function fakeAjax(url) {
    return fetch(url).then(res => {
      if (!res.ok) {
        throw new Error("HTTP error " + res.status);
      }
      return res.json();
    });
  }

  function fetchChildNodes(id) {
    // Should in reality be "URL/id", but fake JSON for now
    return fakeAjax(`https://api.myjson.com/bins/1aqhsc`);
  }

  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 {...node} />))
      );
    }
  };

  return (
    <TreeView
      defaultCollapseIcon={<ExpandMoreIcon />}
      defaultExpandIcon={<ChevronRightIcon />}
      expanded={expanded}
      onNodeToggle={handleChange}
    >
      {/*The node below should act as the root node for now */}
      <TreeItem nodeId="1" label="Applications">
        {/*The childnodes should be here*/}
      </TreeItem>
    </TreeView>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MyTreeItem />, rootElement);

1 个答案:

答案 0 :(得分:1)

在您的示例中,您似乎正在尝试构建树,其中每个有子节点也将是树。

在这种情况下,渲染将如下所示:

{/*The node below should act as the root node for now */}
<TreeItem nodeId={props.id} label={props.name}>
    {childNodes || [<div key="stub" />]} // stub div is used so user could see expand icon
</TreeItem>
// you also need to pass props for root items
ReactDOM.render(<MyTreeItem id="1" name="Applications" />, rootElement);

您可以在此处查看工作代码:https://codesandbox.io/s/material-demo-k5ol6

有多种渲染树的方法。一种是对树结构进行建模并以某种方式进行渲染,以使每个拥有子节点的节点不再是具有局部状态的另一棵树,就像在您的实现中一样。这种方法的优势在于,您不仅可以通过“展开”操作获取树,还可以通过道具提供完整的树。

以下是这种方法的示例:https://codesandbox.io/s/material-demo-h6zfe

此外,您可以将树呈现为列表,其中每个嵌套级别都有一个通过样式指定的偏移量。当您需要分别在每个级别上进行分页时(如果单个级别上有很多项目),这具有优势。实现并不像上面的情况那么容易,因此我将不提供示例。