Search code examples
javascriptreactjsalgorithm

How to render my components in a tree structure, like default file structure in IDE using React


I have a component, which is called TreeNode, it is 1 file in my tree stucture.

import React from "react";
import classes from "./TreeNode.module.css"

function TreeNode({children, title}){
    return(
        <div>
            <div className={classes.treeNode}>
                <div className={classes.treeNodeType}>
                    <svg xmlns="http://www.w3.org/2000/svg" fill="#3B4045" x="0px" y="0px" width="20" height="20" viewBox="0 0 20 20">
                        <path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z"></path>
                    </svg>
                </div>
                <div className={classes.treeNodeTitle}>
                    {title}
                </div>
            </div>
        </div>
    )
}

export default TreeNode;

And i have file, which contain mock-objects of file, i want to drow in my page like a tree.

const files = [
    {
        id: 232141332,
        title: "Оборудование",
        type: "FOALDER",
        opened: false,
        level: 0,
        fatherId: null,
        children: [
            {
                id: 734573086,
                title: "MA5600",
                type: "FOALDER",
                opened: false,
                level: 1,
                fatherId: 232141332,
                children: [
                    {
                        id: 867407333,
                        title: "Удаление платы",
                        type: "FILE",
                        opened: false,
                        level: 2,
                        fatherId: 734573086,
                        children: []
                    },
                    {
                        id: 110345245,
                        title: "Добавление платы",
                        type: "FILE",
                        opened: false,
                        level: 2,
                        fatherId: 734573086,
                        children: []
                    }
                ]
            },
            {
                id: 222225454,
                title: "C300M",
                type: "FOALDER",
                opened: false,
                level: 1,
                fatherId: 232141332,
                children: [
                    {
                        id: 333334256,
                        title: "Не найдена опция TR-82",
                        type: "FILE",
                        opened: false,
                        level: 2,
                        fatherId: 222225454,
                        children: []
                    }
                ]
            }
        ]
    }
]

export default files;

How to write my Main.jsx file to render all this files.

import files from "../../mock/files";
import "../../styles/Main.css"
import TreeNode from "../treenode/TreeNode";

function Main() {
    return (
      <div className="wrapper">
        <div className="tree">
            {
                files.map((file) => {
                    //code
                })
            }
        </div>
      </div>
    );
  }
  
  export default Main;

Maybe I need to refactor some code, i don't know, but the second day I can't do this.


Solution

  • Just use the recursion. Similar to this stackoverflow question.

    Tweaked your component a bit but I hope you understand the overall idea.

    const files = [
      {
        id: 232141332,
        title: "Оборудование",
        type: "FOALDER",
        opened: false,
        level: 0,
        fatherId: null,
        children: [
          {
            id: 734573086,
            title: "MA5600",
            type: "FOALDER",
            opened: false,
            level: 1,
            fatherId: 232141332,
            children: [
              {
                id: 867407333,
                title: "Удаление платы",
                type: "FILE",
                opened: false,
                level: 2,
                fatherId: 734573086,
                children: [],
              },
              {
                id: 110345245,
                title: "Добавление платы",
                type: "FILE",
                opened: false,
                level: 2,
                fatherId: 734573086,
                children: [],
              },
            ],
          },
          {
            id: 222225454,
            title: "C300M",
            type: "FOALDER",
            opened: false,
            level: 1,
            fatherId: 232141332,
            children: [
              {
                id: 333334256,
                title: "Не найдена опция TR-82",
                type: "FILE",
                opened: false,
                level: 2,
                fatherId: 222225454,
                children: [],
              },
            ],
          },
        ],
      },
    ];
    
    const classes = {/* dummy to prevent runtime errors*/};
    
    function TreeNode({ item }) {
      return (
        <div className={classes.treeNode}>
          <div className={classes.treeNodeType}>
            <svg
              xmlns="http://www.w3.org/2000/svg"
              fill="#3B4045"
              x="0px"
              y="0px"
              width="20"
              height="20"
              viewBox="0 0 20 20"
            >
              <path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z"></path>
            </svg>
          </div>
          <div className={classes.treeNodeTitle}>{item.title}</div>
          <div>
            {item.children?.map((x) => (
              <TreeNode key={x.id} item={x} />
            ))}
          </div>
        </div>
      );
    }
    
    const App = () => {
      return (
        <div>
          {files.map((x) => (
            <TreeNode key={x.id} item={x} />
          ))}
        </div>
      );
    };
    
    ReactDOM.render(<App/>, document.getElementById('app'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="app"/>