最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create nested JSX list items from multi-level nested array of objects reactjs - Stack Overflow

programmeradmin6浏览0评论

I am trying to create a nested JSX list items from nested object array. 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. Please help provide a solution.
P.S.: I apologize in advance if you find something wrong with formatting. This is the first time I am posting on stackOverflow.

I am trying to create a nested JSX list items from nested object array. 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. Please help provide a solution.
P.S.: I apologize in advance if you find something wrong with formatting. This is the first time I am posting on stackOverflow.

Share Improve this question asked Dec 14, 2018 at 3:24 ArchitArchit 631 silver badge4 bronze badges 1
  • Two suggestions: 1) create Different parent & ponents for the differing data-structures. 2) If the nested goes deeper you may want to create something higher order and use recursion. – Jefftopia Commented Dec 14, 2018 at 3:28
Add a ment  | 

4 Answers 4

Reset to default 12

You can "render" your children into a variable and use this directly in your ponent. The trick then is to use a recursive ponent. That way it doesn‘t matter how deep your tree is. You don‘t need to edit this ponent 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.

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. You can simplify it more by using 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

发布评论

评论列表(0)

  1. 暂无评论