Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively render a deep nested data in React

Tags:

reactjs

I'm new to react and I want to render a object in sidenav. I have used map function to loop through the object, but I get map is not defined error. Provide me the complete for-loop syntax to render the object.

var side = ({
  "children": [
    {
      "children": [
        {
          "id": "b123a",
          "name": "compo"
        },
        {
          "id": "5a523",
          "name": "orient"
        },
        {
          "id": "42e7e",
          "name": "build"
        }
      ],
      "id": "f9ca7",
      "name": "building"
    },
    {
      "children": [
        {
          "id": "dbd4",
          "name": "insula"
        },
        {
          "id": "ad8404",
          "name": "fenest"
        },
        {
          "id": "e3837",
          "name": "window"
        }
      ],
      "id": "af776",
      "name": "envelope"
    },
    {
      "children": [
        {
          "id": "ba515",
          "name": "heating"
        },
        {
          "id": "6618",
          "name": "cooling"
        },
        {
          "id": "4a0547b8f",
          "name": "water_heating_system"
        }
      ],
      "id": "3e967",
      "name": "systems"
    },
    {
      "id": "e7c6e",
      "name": "spatial"
    },
    {
      "id": "9f641",
      "name": "design"
    }
  ],
  "name": "root"
})

And my html code is

<li>
                <a className="sidenav-title" href="#"><img src="/assets/img/primary/cube.png" style={{width: '20px',marginRight:'10px'}} />
                  <span>Building Form</span>
                </a>
                <a className="collapsible-header arrow-r">
                  <i className="fa fa-angle-down rotate-icon"></i>
                </a>
                <div className="collapsible-body">
                  <ul className="">
                    <li><a href="#" className="">Orientation</a></li>
                    <li><a href="#" className="">Volume</a></li>
                    <li className="li_hover_dropdown">
                      <div className="dropright posti-rel">
                        <a className="sidenav-title1 " href="#">Components</a>
                        <a className="nav-link arrow-r" href="#" style={{padding:'0px'}} data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                          <i className="fa fa-angle-right" style={{marginLeft: '25px'}}></i>
                        </a>
                        <div className="dropdown-menu sidenav-side">
                          <a style={{height:'0px'}}></a>
                          <a className="dropdown-item" href="#">Wall Type</a>
                          <a className="dropdown-item" href="#">Roof Type</a>
                          <a className="dropdown-item" href="#">Substructure Type</a>
                        </div>
                      </div>
                    </li>
                  <li><a href="#" className="">Glazing Size</a></li>
                  <li><a href="#" className=" fadein-color" style={{color:'rgba(0,0,0,34%)!important'}}>Shading Design</a></li>
                </ul>
              </div>
            </li>

In my sidenav I am using three types of menu. First parent is in normal view and second child is in dropdown that opens downwards and third menu is a dropdown that opens to the right.

like image 582
niranchan Avatar asked Jul 06 '18 07:07

niranchan


2 Answers

You need to recursively render your data. At the initial top-level render the object like this

const side = {
  "children": [
    {
      "children": [
        {
          "id": "b123a",
          "name": "compo"
        },
        {
          "id": "5a523",
          "name": "orient"
        },
        {
          "id": "42e7e",
          "name": "build"
        }
      ],
      "id": "f9ca7",
      "name": "building"
    },
    {
      "children": [
        {
          "id": "dbd4",
          "name": "insula"
        },
        {
          "id": "ad8404",
          "name": "fenest"
        },
        {
          "id": "e3837",
          "name": "window"
        }
      ],
      "id": "af776",
      "name": "envelope"
    },
    {
      "children": [
        {
          "id": "ba515",
          "name": "heating"
        },
        {
          "id": "6618",
          "name": "cooling"
        },
        {
          "id": "4a0547b8f",
          "name": "water_heating_system"
        }
      ],
      "id": "3e967",
      "name": "systems"
    },
    {
      "id": "e7c6e",
      "name": "spatial"
    },
    {
      "id": "9f641",
      "name": "design"
    }
  ],
  "name": "root"
}

const SideMenu = ({data}) => {
  if(!data) {
      return null;
  }
  return (
    <ul>
      {
      Array.isArray(data)? data.map(item => {
        return (<li>
          {item.name}
          {item.children && <SideMenu data={item.children} />}
        </li>);
      }): <li>
          {data.name}
          {data.children && <SideMenu data={data.children} />}
        </li>
      }
    </ul>
  );
}

ReactDOM.render(<SideMenu data={side} />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"/>
like image 172
Shubham Khatri Avatar answered Oct 06 '22 10:10

Shubham Khatri


I made the answer with above results please make use of it,

    <div className={level === 3 ?'collapsible-body':'' || level === 4 ?"dropdown-menu sidenav-side":''}>
<ul className={level === 2?'collapsible collapsible-accordion side-nav-link': ""}>
  {
  Array.isArray(data)? data.map(item => {
    return (
      <li className={level === 3?'li_hover_dropdown dropright posti-rel':''}>
        <a  className={level === 2?'sidenav-title':'' ||(level=== 3 && item.children)?"sidenav-title1":''} href="#"><img src={level === 2?'/assets/img/primary/cube.png':""} style={{width: '20px',marginRight:'10px'}} />
          <span>{item.name}</span>
        </a>
        <a className={level === 2   ?'collapsible-header arrow-r':'' || (level === 3 && item.children)?"nav-link arrow-r":'hidden-side'}>
            <i className={level === 2  ?'fa fa-angle-down rotate-icon':'' || (level=== 3 && item.children)?"fa fa-angle-right":'hidden-side'}></i>
        </a>
            {item.children && <SideMenu data={item.children} level={level+1}/>}
      </li>);
    }):
      <li>
        {data.name}
        {data.children && <SideMenu data={data.children} level={level+1}/>}
      </li>
  }
</ul>

and the sidemenu is

<SideMenu data={side} level={1} />
like image 42
niranchan Avatar answered Oct 06 '22 08:10

niranchan