Home > Mobile >  How to build a recursive function
How to build a recursive function

Time:07-08

Having a bit of an issue regarding recursive functions that I can not wrap my head around and was wondering if I can get some help.

I have a json object like so below

const data = {
    "navItems": [
        {
            "type": "directory",
            "name": "Nav Title 1",
            "children": [
                {
                    "downloadUrl": "",
                    "content": "",
                    "type": "file",
                    "name": "File 1.pdf"
                },
                {
                    "downloadUrl": "",
                    "content": "",
                    "type": "file",
                    "name": "File 2.pdf"
                },
                {
                    "type": "directory",
                    "name": "Sub Title 1",
                    "children": [
                        {
                            "downloadUrl": "",
                            "content": "",
                            "type": "file",
                            "name": "Sub File 1.pdf"
                        },
                        {
                            "downloadUrl": "",
                            "content": "",
                            "type": "file",
                            "name": "Sub File 2.docx"
                        }
                    ]
                },
                {
                    "type": "directory",
                    "name": "Sub Title 2",
                    "children": [
                        {
                            "type": "directory",
                            "name": "Sub Sub Title 1",
                            "children": [
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 1.pdf"
                                },
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 2.pdf"
                                }
                            ]
                        },
                        {
                            "type": "directory",
                            "name": "Sub Sub Title 2",
                            "children": [
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 1.pdf"
                                },
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 2.pdf"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

that I need to dynamically create a nav menu in react with this data set in a way it looks like this

let newNavItem = {
    id: 'apps.'   id,
    title: item.name,
    type: 'collapse',
    icon: 'heroicons-outline:folder',
    children: [
      {
         id: 'paper.'   sub2item.name,
         title: sub2item.name,
         type: 'item',
         url: sub2item.downloadUrl,
      }
    ]
  }

Example of a collapsible nav item (type = Directory)

 {
    id: id,
    title: title,
    type: 'collapse',
    icon: 'heroicons-outline:folder',
    children: []
  }

Example of a clickable URL that would go inside the children array: (type = File)


{
   id: id,
   title: name,
   type: 'item',
   url: url,
}

EDIT: this is currently where I've gotten with the function.

const buildNavBlock = (navItem) => {
        if (navItem.hasOwnProperty("children") && navItem.children.length > 0 && navItem.type == "directory") {
      console.log(navItem.children);
        return {
              id: 'apps.'   navItem.name,
              title: navItem.name,
              type: 'collapse',
              icon: 'heroicons-outline:folder',
              children: buildNavBlock(navItem.children)
      }
    } else {
       return {
         id: 'paper.'   navItem.name,
         title: navItem.name,
         type: 'item',
         url: 'apps/documents/',
       }
    }
};

data.navItems.forEach((item => {
  let nav = buildNavBlock(item);
  console.log(nav);
}))

CodePudding user response:

Seems when you are calling your recursive function you aren't calling it for each of the children. Changing it to this may help:

const buildNavBlock = (navItem) => {
        if (navItem.hasOwnProperty("children") && navItem.children.length > 0 && navItem.type == "directory") {
      console.log(navItem.children);
        return {
              id: 'apps.'   navItem.name,
              title: navItem.name,
              type: 'collapse',
              icon: 'heroicons-outline:folder',
              children: navItem.children.map(child => buildNavBlock(child))
      }
    } else {
       return {
         id: 'paper.'   navItem.name,
         title: navItem.name,
         type: 'item',
         url: 'apps/documents/',
       }
    }
};

data.navItems.forEach((item => {
  let nav = buildNavBlock(item);
  console.log(nav);
}))

CodePudding user response:

it's might help

const data = {
    "navItems": [
        {
            "type": "directory",
            "name": "Nav Title 1",
            "children": [
                {
                    "downloadUrl": "",
                    "content": "",
                    "type": "file",
                    "name": "File 1.pdf"
                },
                {
                    "downloadUrl": "",
                    "content": "",
                    "type": "file",
                    "name": "File 2.pdf"
                },
                {
                    "type": "directory",
                    "name": "Sub Title 1",
                    "children": [
                        {
                            "downloadUrl": "",
                            "content": "",
                            "type": "file",
                            "name": "Sub File 1.pdf"
                        },
                        {
                            "downloadUrl": "",
                            "content": "",
                            "type": "file",
                            "name": "Sub File 2.docx"
                        }
                    ]
                },
                {
                    "type": "directory",
                    "name": "Sub Title 2",
                    "children": [
                        {
                            "type": "directory",
                            "name": "Sub Sub Title 1",
                            "children": [
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 1.pdf"
                                },
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 2.pdf"
                                }
                            ]
                        },
                        {
                            "type": "directory",
                            "name": "Sub Sub Title 2",
                            "children": [
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 1.pdf"
                                },
                                {
                                    "downloadUrl": "",
                                    "content": "",
                                    "type": "file",
                                    "name": "Sub Sub File 2.pdf"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}
/*let newNavItem = {
    id: 'apps.'   id,
    title: item.name,
    type: 'collapse',
    icon: 'heroicons-outline:folder',
    children: [
      {
         id: 'paper.'   sub2item.name,
         title: sub2item.name,
         type: 'item',
         url: sub2item.downloadUrl,
      }
    ]
  }*/
const {useEffect, useState} = React

const Dir=({data, isActive=true, collapsed=true})=>{
  const [active,setActive]=useState(!collapsed)
  return <li className={"dir " (isActive ? "active":"nested")}   href="">
  {data.title}
  <span className={"caret " (active?"caret-down":"")} onClick={()=>setActive(v=>!v)}/>
  <ul>
  {(data.children || []).map(v=>v.type==="collapse"?
    <Dir key={v.id} data={v} isActive={active}/>:<File key={v.id} data={v} isActive={active}/>)}
    </ul>
    </li>
 
}

const File=({data,isActive})=>{
  return <li className={"file " (isActive ? "active":"nested")}  href={data.url}>
   {data.title}</li>
}

const App=(props)=>{
  const makeNav=(data)=> (data.type === "directory")?
    {
      id: 'paper.'   data.name,
      title: data.name,
      type: 'collapse',
      icon: 'heroicons-outline:folder',
      children: (data.children||[]).map(v=>makeNav(v))
    }:(data.type === "file")?
    {
     id: 'paper.'   data.name,
     title: data.name,
     type: 'item',
     url: data.downloadUrl,
    }:""

 
  const [nav, setNav]=useState([])
  useEffect(()=>{
  let v=props.data.navItems.map(v=>makeNav(v))
    setNav(v)
    //console.log(v)
  },[])
  return   <div >
  <ul>
  {nav.map(v=>v.type==="collapse"?
  <Dir key={v.id} data={v}/>:<File key={v.id} data={v}/>)}
  </ul>
</div>
}
ReactDOM.render(<App data={data}/>,document.getElementById('app'))
/* Style sidebar links */
.sidebar li {
  padding: 6px 8px 6px 16px;
  text-decoration: none;
  font-size: 20px;
  color: #818181;
  
}

/* Style links on mouse-over */
.sidebar li:hover {
  color: #f1f1f1;
}

.caret {
  cursor: pointer;
  user-select: none; /* Prevent text selection */
}

/* Create the caret/arrow with a unicode, and style it */
.caret::before {
  content: "\25B6";
  color: black;
  display: inline-block;
  margin-right: 6px;
}

/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.caret-down::before {
  transform: rotate(90deg);
}

/* Hide the nested list */
.nested {
  display: none;
}

/* Show the nested list when the user clicks on the caret/arrow (with JavaScript) */
.active {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<div id="app">
</div>

  • Related