简体   繁体   English

通过嵌套的 object 反应循环

[英]React loop through nested object

I'm fetching data from strapi.我正在从strapi 获取数据。 The response for my navigation object looks like that (simplified):我的导航 object 的响应看起来像这样(简化):

[
   {
      "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) (因为 object 可以嵌套很多次)

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;

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.如果您对深度优先遍历或递归不满意,我会建议您首先通过以下代码段使用 go。

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.一旦你觉得舒服了,你就可以把它翻译成 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>
  );
}

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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM