最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - TreeView - Check if expanded and onClick - Stack Overflow

programmeradmin3浏览0评论

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
Add a ment  | 

2 Answers 2

Reset to default 5

Answering 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)
}
发布评论

评论列表(0)

  1. 暂无评论