Selaminko Elam
Selaminko Elam

Reputation: 193

How to recursively render React components based on a deeply nested array?

with react js I'm trying to reach the continuing list as child in child child ... but here's the thing I'm stuck with, How can I list it? To give an example, I want the schema to be as follows

please keep in mind that I am new to react js when replying to or reading this thread. I may have a hard time Expressing Myself.

Menu 1 Menu Title
Menu 2 Menu Title
--Menu 2.1 Menu category-header
--Menu 2.2 Menu category-header
--Menu 2.3 Menu category-header
---Menu 2.3.1 Menu sub-category-header
---Menu 2.3.2 Menu sub-category-header
---Menu 2.3.3 Menu sub-category-header
----Menu 2.3.3.1 Menu sub-sub-category-header
----Menu 2.3.3.2 Menu sub-sub-category-header
const menuData = [
        {
            name: "Menu 1",
            url: "/"
        },
        {
            name: "Menu 2",
            children: [
                {
                    name: "Menu 2.1",
                    url: "/page/menu-2-1"
                },
                {
                    name: "Menu 2.2",
                    url: "/page/menu-4-2"
                },
                {
                    name: "Menu 2.3",
                    children: [
                        {
                            name: "Menu 2.3.1",
                            url: "/page/menu-2-3-1"
                        },
                        {
                            name: "Menu 2.3.2",
                            url: "/page/menu-2-3-2"
                        },
                        {
                            name: "Menu 2.3.3",
                            children: [
                                {
                                    name: "Menu 2.3.3.1",
                                    children: [
                                        {
                                            name: "Menu 2.3.3.1.1",
                                            url: "/page/menu-2-3-3-1-1"
                                        },
                                        {
                                            name: "Menu 2.3.3.1.2",
                                            url: "/page/menu-2-3-3-1-2"
                                        }
                                    ]
                                },
                                {
                                    name: "Menu 4.3.3.2",
                                    url: "/page/menu-4-3-3-2"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
const Menu = ({data}) => {
    const renderMenuItems = data => {
        return data.map(
            (item, index) =>
                (item?.children && item?.children.length) ?
                    (
                        console.log(item)
                    ) :
                    <li className="nav-item" key={index}>
                        <Link className="nav-link" to={item.url}>{item.name}</Link>
                    </li>

        )
    }
    return data && (
        <nav className="navbar navbar-expand-md navbar-main border-bottom">
            <div className="container">
                <div className="collapse navbar-collapse mobile-menu">
                    <ul className="nav navbar-nav">
                        {renderMenuItems(data)}
                    </ul>
                </div>
            </div>
        </nav>

    );
}
export default Menu;
<nav>
    <ul>
        <li>
            <a href="url">Menu 1</a>
        </li>
        <li>
            <a href="url" class="category-header">Woman</a>
            <div class="sub-nav">
                <div class="sub-nav-center">
                    <div class="sub-nav-outer">
                        <div class="normal-column">
                            <div class="category-box">
                                <a href="url" class="sub-category-header">Clothes</a>
                                <ul class="sub-item-list">
                                    <li>
                                        <a href="">T-shirt</a>
                                    </li>
                                    <li>
                                        <a href="">Shorts</a>
                                    </li>
                                    <li>
                                        <a href="">Shirt</a>
                                    </li>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </li>
    </ul>
</nav>

enter image description here

enter image description here

Upvotes: 2

Views: 3458

Answers (1)

Ramesh Reddy
Ramesh Reddy

Reputation: 10662

You have to recursively render each element until an element no longer has children.

I created a simple example using your data. Here, List maps and renders ListItem for each element of the array and ListItem again renders List if the element has children.

You can do something similar using your components.

const { useState, useEffect } = React;

const menuData = [
  {
    name: 'Menu 1',
    url: '/',
  },
  {
    name: 'Menu 2',
    children: [
      {
        name: 'Menu 2.1',
        url: '/page/menu-2-1',
      },
      {
        name: 'Menu 2.2',
        url: '/page/menu-4-2',
      },
      {
        name: 'Menu 2.3',
        children: [
          {
            name: 'Menu 2.3.1',
            url: '/page/menu-2-3-1',
          },
          {
            name: 'Menu 2.3.2',
            url: '/page/menu-2-3-2',
          },
          {
            name: 'Menu 2.3.3',
            children: [
              {
                name: 'Menu 2.3.3.1',
                children: [
                  {
                    name: 'Menu 2.3.3.1.1',
                    url: '/page/menu-2-3-3-1-1',
                  },
                  {
                    name: 'Menu 2.3.3.1.2',
                    url: '/page/menu-2-3-3-1-2',
                  },
                ],
              },
              {
                name: 'Menu 4.3.3.2',
                url: '/page/menu-4-3-3-2',
              },
            ],
          },
        ],
      },
    ],
  },
];

function ListItem({ listItem }) {
  const { name, url, children } = listItem;
  return (
    <li>
      <p>
        {name} - {url}
      </p>
      {Array.isArray(children) && <List list={children} />}
    </li>
  );
}

function List({ list }) {
  return (
    <ul>
      {list.map((listItem) => (
        <ListItem key={listItem.name} listItem={listItem} />
      ))}
    </ul>
  );
}
function App() {
  return <List list={menuData} />;
}

ReactDOM.render(<App />, document.querySelector('#root'));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

Upvotes: 5

Related Questions