I'm fetching data from strapi. The response for my navigation object looks like that (simplified):
[
{
"id":1,
"title":"Home",
"order":1,
"items":[
{
"id":2,
"title":"3D Assets",
"order":1,
"items":[
]
},
{
"id":4,
"title":"3D Plants",
"order":2,
"items":[
]
},
{
"id":3,
"title":"Surfaces",
"order":3,
"items":[
{
"id":5,
"title":"Asphalt",
"order":1,
"items":[
]
}
]
}
]
},
{
"id":6,
"title":"Collections",
"order":2,
"items":[
],
"icon":""
}
]
Actually I'm looping through my navigation like that:
{Object.entries(navigationItems).map(([key, value]) => {
return(
<div className="nav_item">
<div className="nav_item_parent">{value.title}
{Object.entries(value.items).map(([key, value]) => {
return(
<div className="nav_item_child">{value.title}
{Object.entries(value.items).map(([key, value]) => {
return(
<div className="nav_item_child">{value.title}</div>
)
})}
</div>
)
})}
</div>
</div>
)
})}
How can I create a navigation without repeating the code for each child? (Because the object could be nested many times)
CodePudding user response:
Here just placing some demo code , please have reference and implement as per your need Parent Component
import React, {Children} from 'react';
function recursionExample(props) {
let data = [
{
id: 1,
title: 'Home',
order: 1,
items: [
{
id: 2,
title: '3D Assets',
order: 1,
items: [],
},
{
id: 4,
title: '3D Plants',
order: 2,
items: [],
},
{
id: 3,
title: 'Surfaces',
order: 3,
items: [
{
id: 5,
title: 'Asphalt',
order: 1,
items: [],
},
],
},
],
},
{
id: 6,
title: 'Collections',
order: 2,
items: [],
icon: '',
},
];
return (
<div>
{data.map((item, index) => {
return (
<>
<div>{item.title}</div>
{item.items && <ChildrenCom data={item.items}></ChildrenCom>}
</>
);
})}
</div>
);
}
export default recursionExample;
Now below component will call till last-child , as it is called recursively
import React from 'react';
function ChildrenCom(props) {
let {data} = props;
return (
<div>
{data.map((item, index) => {
return (
<>
<div>{item.title}</div>
{item.items && <ChildrenCom data={item.items}></ChildrenCom>}
</>
);
})}
</div>
);
}
export default ChildrenCom;
CodePudding user response:
We could use Depth First Traversal to help us avoid duplication. If you're not comfortable with Depth First Traversal or Recursion, I would recommend you to go through the following snippet initially.
function dfs(item, depth = 0) {
if (!item || Object.keys(item).length === 0) return;
console.log("\t".repeat(depth), item.title);
for (const subItem of item.items) {
dfs(subItem, depth 1);
}
}
// Consider payload to be the response that you get from the API.
for (const item of payload) {
dfs(item)
}
Once you're comfortable, you could translate it into React.
const Nav = ({ item, depth = 0 }) => {
if (!item || Object.keys(item).length === 0) return;
return (
<>
<p style={{ paddingLeft: `${depth * 64}px` }}>{item.title}</p>
{item.items.map((subItem, index) => (
<Nav item={subItem} depth={depth 1} />
))}
</>
);
};
export default function App() {
return (
<div className="App">
{payload.map((item) => (
<Nav item={item} />
))}
</div>
);
}
CodePudding user response:
Just a simple recursive tree walk. A component like this:
const NodePropTypes = PropTypes.objectWithShape({
id: PropTypes.number,
title: PropTypes.string,
items: PropTypes.array,
});
const NavListPropTypes = {
nodes: PropTypes.arrayOf( NodePropTypes ),
};
function NavList( props ) {
const nodes = props?.nodes ?? [];
if (nav.length) {
return (
<list>
<ListItems nodes={nodes} />
</list>
);
}
}
NavList.propTypes = NavListPropTypes
function ListItems( props ) {
const nodes = props?.nodes ?? [];
return (
<>
{ nodes.map( node => <ListItem node={node} /> ) }
</>
);
}
ListItems.propTypes = NavListPropTypes;
function ListItem( props ) {
const node = props?.node ?? {};
return (
<li id={node.id} >
<p> {node.title} </p>
<NavList nodes={node.items} />
</li>
);
}
ListItem.propTypes = NodePropTypes;
which can be rendered passing your navigation response:
<NavList nodes={navigationResponse} />
And should yield something like this:
<list>
<li id="1" >
<p> Home </p>
<list>
<li id="2" >
<p> 3D Assets </p>
</li>
<li id="4" >
<p> 3d Plants </p>
</li>
<li id="3" >
<p> Surfaces </p>
<list>
<li id="5" >
<p> Asphalt </p>
</li>
</list>
</li>
</list>
</li>
<li id="6" >
<p> Collections </p>
</li>
</list>