React:通过嵌套对象循环

问题描述:

我正在从strapi 获取数据。我的导航对象的响应如下所示(简化):

[
   {
      "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":""
   }
]

实际上,我正在像这样循环浏览我的导航:

{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>
    )
})}

 

如何在不为每个孩子重复代码的情况下创建导航?(因为对象可以嵌套很多次)

解决思路一:

我们可以使用深度优先遍历来帮助我们避免重复。如果您对深度优先遍历或递归不满意,我建议您先阅读以下代码段。

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)
}

你就可以把它翻译成 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>
  );
}

解决思路二:

只是一个简单的递归树遍历。像这样的组件:

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;

可以通过您的导航响应呈现:

<NavList nodes={navigationResponse} />

并且应该产生这样的结果:

<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>

解决思路三(这是解决小编问题的思路)

以上仅为部分解决思路,添加下方公众号后回复001,即可查看全部内容。公众号有许多评分最高的编程书籍和其它实用工具,无套路,可放心使用

如果您觉得有帮助,可以关注公众号——定期发布编程科技相关的资讯和资源

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快撑死的鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值