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

时间:2018-12-14 03:24:14

标签: javascript reactjs

我正在尝试从嵌套对象数组创建嵌套JSX列表项。 下面是数组:

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

下面是数组应转换为的内容:

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

这是我的方法:

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不允许将单独的标记添加到数组中。请帮助提供解决方案。
附注:如果您发现格式化有误,我先向您致歉。这是我第一次在stackOverflow上发帖。

4 个答案:

答案 0 :(得分:2)

您可以将孩子“渲染”为变量,然后直接在组件中使用它。 然后,诀窍是使用递归组件。这样,您的树有多深都没关系。如果树变得更深,则无需编辑此组件。

这可能是这样的:

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

这是Codesandbox上您的数据的有效示例。

答案 1 :(得分:0)

您应立即将整个节点推入阵列。有一个这样的渲染方法。

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

然后在渲染函数中使用数据调用该方法

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

export default Layout;

答案 2 :(得分:0)

这是一个使用模板的完整解决方案示例,该模板在语法上类似于React。您可以使用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>
        );

    }
}

答案 3 :(得分:0)

我也有同样的问题,但是我已经有了一个脚本,因此我只是在寻找一个更简单的解决方案。此处的脚本可能会有所帮助。

// Render a Nested Element based on nested Array