简体   繁体   English

从对象的多层嵌套数组reactjs创建嵌套的JSX列表项

[英]Create nested JSX list items from multi-level nested array of objects reactjs

I am trying to create a nested JSX list items from nested object array. 我正在尝试从嵌套对象数组创建嵌套JSX列表项。 Below is the array: 下面是数组:

[
  {
    "id": 1,
    "name": "USA",
    "values": [
      {
        "id": 2,
        "name": "Chevy",
        "values": [
          {
            "id": 3,
            "name": "Suburban"
          },
          {
            "id": 4,
            "name": "Camaro",
            "values": [...]
          }
        ]
      },
      {
       "id": 5,
       "name": "Ford",
       "values": [...]
      }
    ]
  }
]

Below is what the array should be converted to: 下面是数组应转换为的内容:

<ul>
  <li>USA
    <ul>
      <li>Chevy
        <ul>
          <li>Suburban</li>
          <li>Camaro</li>
        </ul>
      </li>
      <li>Ford</li>
    </ul>
  </li>
</ul>

Here is my approach: 这是我的方法:

const resultArray = [];
data.forEach((item) => {
  resultArray.push(
    <li>{item.name}
  )
  if(item.values){
   //recursively iterate and push into array
  }
  resultArray.push(</li>); //React does not allow this
});
return resultArray;

React does not allow adding individual markups into array. React不允许将单独的标记添加到数组中。 Please help provide a solution. 请帮助提供解决方案。
PS: I apologize in advance if you find something wrong with formatting. PS:如果您发现格式化有误,我深表歉意。 This is the first time I am posting on stackOverflow. 这是我第一次在stackOverflow上发帖。

You can "render" your children into a variable and use this directly in your component. 您可以将孩子“渲染”为变量,然后直接在组件中使用它。 The trick then is to use a recursive component. 然后,诀窍是使用递归组件。 That way it doesn't matter how deep your tree is. 这样,您的树有多深都无所谓。 You don't need to edit this component if your tree gets deeper. 如果树变得更深,则不需要编辑此组件。

Here is how that might look like: 这可能是这样的:

function ListItem({ item }) {
  let children = null;
  if (item.values) {
    children = (
      <ul>
        {item.values.map(i => <ListItem item={i} key={i.id} />)}
      </ul>
    );
  }

  return (
    <li>
      {item.name}
      {children}
    </li>
  );
}

Here is a working example on Codesandbox with your data. 这是Codesandbox上数据的有效示例。

You should push the entire node to the array at once. 您应该立即将整个节点推入阵列。 Have a render method like this. 有一个这样的渲染方法。

const getNode = (data) => {
  return (
    <ul>
      {data.map((item) => (
        <li>
          USA
          <ul>
            {item.values && item.values.length
              ? item.values.map((subItem) => (
                  <li>
                    {subItem.name}
                    <ul>
                      {subItem.values && subItem.values.length
                        ? subItem.values.map((subSubItem) => <li>{subSubItem.name}</li>)
                        : null}
                    </ul>
                  </li>
                ))
              : null}
          </ul>
        </li>
      ))}
    </ul>
  );
};

And call that method in your render function with the data 并在渲染函数中使用数据调用该方法

const RenderList = (data) => {
  return (
    <div>
      { getNode(data) }
    </div>
  );
};

export default Layout;

Here's a full solution example using stencil, which is a framework syntactically similar to React. 这是一个使用模板的完整解决方案示例,该模板在语法上类似于React。 You can simplify it more by using Array.prototype.reduce . 您可以使用Array.prototype.reduce进一步简化它。

import { Component, State } from '@stencil/core';

@Component({
    tag: 'app-nested-list-demo'
})
export class NestedList {

    @State() foo = [
        {
            name: 'US',
            makers: [
                {
                    name: 'Ford',
                    models: [
                        {
                            name: 'Suburban',
                            mpg: '9000'
                        },
                        {
                            name: 'Escape',
                            mpg: '300'
                        }
                    ]
                },
                {
                    name: 'GMC',
                    models: [
                        {
                            name: 'Acadia',
                            mpg: '11'
                        },
                        {
                            name: 'Envoy',
                            mpg: 'Yukon'
                        }
                    ]
                }
            ]
        },
        {
            name: 'Japan',
            makers: [
                {
                    name: 'Honda',
                    models: [
                        {
                            name: 'CRV',
                            mpg: '100'
                        },
                        {
                            name: 'Accord',
                            mpg: '9000'
                        }
                    ]
                },
                {
                    name: 'Toyota',
                    models: [
                        {
                            name: 'Rav4',
                            mpg: '10'
                        },
                        {
                            name: 'Camry',
                            mpg: '400'
                        }
                    ]
                }
            ]
        }
    ];

    render() {
        const outerList = this.foo.map(country => {

            const middleList = country.makers.map(make => {

                const innerList = make.models.map(model => {
                    return (
                        <li>{model.name} has {model.mpg} MPG</li>
                    );
                });

                return (
                    <li>
                        {make.name}
                        <ul>
                            {innerList}
                        </ul>
                    </li>
                );

            });

            return (
                <li>
                    {country.name}
                    <ul>
                        {middleList}
                    </ul>
                </li>
            );
        });

        return (
            <ul>
                {outerList}
            </ul>
        );

    }
}

I kind of asked the same thing but I already have a script for it, so I'm just looking for a much simpler solution. 我也问过同样的问题,但是我已经有了一个脚本,所以我只是在寻找一个更简单的解决方案。 The script here might help. 此处的脚本可能会有所帮助。

// Render a Nested Element based on nested Array // 根据嵌套数组渲染嵌套元素

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

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