1

I have to populate the li element with data stored as a JSON object. With "title" it works simple. But it's not when talking about name's values. How can I map the subMenu object to get the name?

    <ul>
      {data.map(({ title, subMenu }) => (
                <li className="mobileMenu-body-nav-item">
                    <button className="mobileMenu-body-nav-item-btn"> 
                 *** here I have to put name ***
                    </button>
                </li>
     ))}
    </ul>
         

JSON object

[
   {
    "title": "Breeds",
    "subMenu": [
        {
            "id": 1,
            "name": "Dog Breeds"
        },
        {
            "id": 2,
            "name": "Cat Breeds"
        }
    ]
  },
  {
    "title": "About Pet Adoption",
    "subMenu": [
        {
            "id": 3,
            "name": "About Dog Adoption"
        },
        {
            "id": 4,
            "name": "About Cat Adoption"
        }
      ]
   }
 ]
pilchard
  • 12,414
  • 5
  • 11
  • 23
Loren
  • 49
  • 6

2 Answers2

3

As noted in the comments on the accepted answer div elements are not valid children of buttons (related question) and while one should assign a key to mapped elements in React using the index of the iterated array is not always ideal. (see the Docs or related article from T.J.Crowder's comment).

Given that you are mapping a nested list it seems more appropriate to structure it as such. Here using the title as the outer li key (though a more definite unique property would be better) and the subMenu.id as a key for the inner li.

<ul>
  {data.map(({ title, subMenu }) => (
    <li key={title} className='mobileMenu-body-nav-item'>
      <ul>
        {subMenu.map(({ id, name }) => (
          <li key={id}>
            <button className='mobileMenu-body-nav-item-btn'>{name}</button>
          </li>
        ))}
      </ul>
    </li>
  ))}
</ul>
pilchard
  • 12,414
  • 5
  • 11
  • 23
2

You can just call map again, like this:

 <ul>
    {data.map(({ title, subMenu }) => (
        <li className="mobileMenu-body-nav-item">
            <button className="mobileMenu-body-nav-item-btn">
                {subMenu.map(({ name }) => (<span>{name}</span>))}
            </button>
        </li>
    ))}
</ul>

Change the <span> tag to match however you want this content to be rendered.

Also, if this is React, don't forget to set the key prop appropriately when using map:

<ul>
    {data.map(({ title, subMenu }) => (
        <li key={title} className="mobileMenu-body-nav-item">
            <button className="mobileMenu-body-nav-item-btn">
                {subMenu.map(({ name }) => (<div key={name}>{name}</div>))}
            </button>
        </li>
    ))}
</ul>
Donut
  • 110,061
  • 20
  • 134
  • 146
  • 2
    So good to see that "Also" at the end. People usually miss pointing that out! – T.J. Crowder Nov 02 '21 at 13:59
  • 2
    Also note that [`div`](https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element) is not a valid child of [`button`](https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element). Perhaps `span`? – T.J. Crowder Nov 02 '21 at 14:03
  • 1
    @T.J.Crowder Thanks for the link! Super good to know, I learned something useful today. – Donut Nov 02 '21 at 14:29