Search code examples
javascriptreactjsnested

How can i create a tree table kind off structure using the nested json using React


Hi everone i have a issue or more over i want to know "How can i create a tree table kind off structure using the nested json". With out using any 3rd part lib/package

I have a nested json like below :

[
  {
    "id": 1,
    "name": "VehicleData",
    "owner": "admin",
    "sub_details": [
      {
        "sub_name": "Lexus",
        "sub_id": 4,
      },
      {
        "sub_name": "BMW",
        "sub_id": 3,
      }
    ]
  },
  {
    "id": 2,
    "name": "Mobiles,
    "owner": "admin",
    "sub_details": [
      {
        "sub_name": "Apple",
        "sub_id": 2,
      }
    ]
  },
  {
    "id": 3,
    "name": "Laptop",
    "owner": "admin",
    "sub_details": []
  }
]

What i have tried :-

import React, {useState, useEffect} from 'react';
import classes from './TableData.module.css';

const TableData = () => {
    const [oldData, newData] = useState([]);

    useEffect(() => {
        fetchData();
    }, []);

    const Id = (dataId) => {
        alert(dataId);
    };
    const Name = (dataName) => {
        alert(dataName);
    };

    const fetchData = async () => {
        try {
            const response = await fetch('someapi/json');
            const data = await response.json();
            newData(data);
        } catch (e) {
            console.warn(e)
        }
    }


    const DisplayData = oldData.map((data) => {
        return (
            <tr key={
                data.id
            }>
                <td> {
                    data.id
                } </td>
                <td> {
                    data.name
                } </td>
                <td> {
                    data.owner
                } </td>
                <td>
                    <button onClick={
                        () => Id(data.id)
                    }>getId</button>
                    <button onClick={
                        () => Name(data.name)
                    }>getname</button>
                </td>
            </tr>
        )
    })


    return (
        <div>
            <div>
                <table>
                    <thead>
                        <tr>
                            <th>id</th>
                            <th>name</th>
                            <th>owner</th>
                        </tr>
                    </thead>
                    <tbody> {DisplayData} </tbody>
                </table>

            </div>


        </div>
    )

}

export default TableData;

what i have done : I have created a table using json and also added button for getting the parent data

what i need and how can i do :

  1. How can i add create the nested structure without using 3rd party plugins and also add button to each row .

  2. How can i get the parent data and child data on each child row button click .

  3. How can i able to toggle & keep open up the nested structure .

if any info url are there it will be great full ?


Solution

  • In React, you must break your data into components. Working with the data as is, in multi-level nesting, is considered bad design - see here for a detailed explanation.

    With this in mind, I dedicated one component for each nesting level. This way, the row can manage its sub-row hidden state. Here's the final code - see full demo here - click the "toggle" button:

    index.js:

    import React, { useState, useEffect } from "react";
    import "./styles.css"
    
    const Table = () => {
      const [items, setItems] = useState([]);
    
      useEffect(() => {
        fetchData();
      }, []);
    
      const fetchData = async () => {
        try {
          const response = await fetch("./data.json");
          const data = await response.json();
          setItems(data);
        } catch (e) {
          console.warn(e);
        }
      };
      
      return <div>
        {
          items.map((data) => { 
            return <TableData key={data.id} data={data} />
          })
        }
      </div>;
    };
    
    const TableData = (props) => {
      const data = props.data;
      const [subHidden, setSubHidden] = useState(false);
      
      const Id = (dataId) => {
        alert(dataId);
      };
      const Name = (dataName) => {
        alert(dataName);
      };
      const Toggle = () => {
        setSubHidden(state => { 
          return !state;
        });
      };
    
      return (
        <div >
          <span> {data.id} </span>
          <span> {data.name} </span>
          <span> {data.owner} </span>
          <span>
            <button onClick={() => Id(data.id)}>getId</button>
            <button onClick={() => Name(data.name)}>getname</button>
            <button onClick={() => Toggle()}>toggle</button>
          </span>
          <TableSubDetails 
            subDetails={data.sub_details}
            style={{ display: subHidden ? 'none' : 'block'}}
          />
        </div>
      );
    }
    
    const TableSubDetails = (props) => {
      const subDetails = props.subDetails;
      return (
        <div className="subData" style={props.style}>
          {
            subDetails.map((subData) => { 
              return <div key={subData.sub_id}>
                <span> {subData.sub_id} </span>
                <span> {subData.sub_name} </span>
              </div>
            })
          }
        </div>
      );
    }
    
    export default Table;
    

    styles.css:

    .subData {
      padding: 5px 15px;
    }