skip to Main Content

How should I iterate through an array of objects in JavaScript using the map() function? I am doing this:

const arr = [
{title: "Title 1", url: "/title1"},
{title: "Title 2", url: "/title2"},
{title: "Title 3", url: "/title3"},
{title: "Title 4", url: "/title4"},
]

arr.map((item, index)=>{
return(

<li key={index}>
<a href={item.url}>{{item.title}}</a>
</li>

)
})

This works fine but what about if I have an array of objects with a nested array of objects? Like,

const arr = [
{title: "Title 1", url: "/title1"},
{title: "Title 2", url: "/title2"},
{title: "Title 3", url: "/title3"},
{title: "Title 4", url: "/title4", subs:[
{title: "Title 1", url: "/title1"},
{title: "Title 2", url: "/title2"},
{title: "Title 3", url: "/title3"},
]},
{title: "Title 5", url: "/title5"},
{title: "Title 6", url: "/title6"},
]

Expected Output:

Title 1
Title 2
Title 3
Title 4
  - Title 1
  - Title 2
  - Title 3
Title 5
Title 6

My Approach

I write following piece of code to get the expected results but having an error Cannot read properties of undefined (reading 'map').

arr.map((item, index)=>{
return(
<ul>
<li key={index}>
<Link href={item.url}>{item.title}</Link>
</li>

{item.subs.map((topic, index)=>{
return(
<li key={index}>
<Link href={topic.url}>{topic.title}</Link>
</li>

)
})}
</ul>
)
})


Please Write me piece of code that works

2

Answers


  1. This seems like a suitable scenario for using a recursive function. Essentially, we can create a general function that calls itself. I have created the function for you. The function takes an array of elements, and iterates over each element. If the element has a "subs" array, it will call itself again and add the results to the "element" variable. If there are no "subs" in the current element, it will simply add it to the current element.

    On another note, there is an alternative method to accomplish this without recursion by utilizing an array of dependencies. If you would like, I can also construct this method for you.

    const arr = [
        { title: "Title 1", url: "/title1" },
        { title: "Title 2", url: "/title2" },
        { title: "Title 3", url: "/title3" },
        {
          title: "Title 4",
          url: "/title4",
          subs: [
            { title: "Title NEST 1", url: "/title1" },
            {
              title: "Title NEST 2",
              url: "/title2",
              subs: [{ title: "Title NEST  NEST X", url: "/titleX" }],
            },
            { title: "Title NEST 3", url: "/title3" },
          ],
        },
      ];
      function arrToElement(arr: Array<any>): JSX.Element {
        debugger;
        let element = (
          <>
            <div>root is here</div>
          </>
        );
        for (const i in arr) {
          const index = parseInt(i);
          // when there is subs
          if (arr[index].subs) {
            element = (
              <>
                <div>
                  {element}
                  <br />
                  plus
                  {index}
                  <div>
                    {arr[index].title} nested <div></div>
                    --{arrToElement(arr[index].subs)}
                  </div>
                </div>
              </>
            );
          }
          else {
            element = (
              <>
                <div>
                  {element}
                  <br />
                  plus
                  {index}
                  <div>
                    {arr[index].title} not nested
                  </div>
                </div>
              </>
            );
          }
        }
        return element;
      }
    
    Login or Signup to reply.
  2. You are probably better of with a recursive function to achieve what you are looking for.

    ReactJS:

    const RenderNested = ({ items }) => {
      return (
        <ul>
          {items.map((item, index) => (
            <li key={index}>
              {item.title}
              {item.subs && <RenderNested items={item.subs} />}
            </li>
          ))}
        </ul>
      );
    };
    
    
    export function App(props) {
      return (
        <div>
          <RenderNested items={arr} />
        </div>
      );
    }
    
    1. RenderNested takes a property called items, that is an array.
    2. RenderNested starts to render our unordered list by looping over it as a map.
    3. If we find an object container subs-object, we recursively call RenderNested that starts over at step 1.
    4. Once no more items, we end our unordered list and return.

    Same concept with Vanilla JavaScript:

    const renderNested = (items) => {
      let render = '<ul>';
      items.forEach((item) => {
        render += '<li>';
        render += item.title;
        if (item.subs) {
          render += '<ul>';
          render += renderNested(item.subs);
          render += '</ul>';
        }
        render += '</li>';
      });
      render += '</ul>';
      return render;
    };
    
    
    const list = document.getElementById("list");
    list.innerHTML = renderNested(arr);
    

    Since it is recursive, you can basically have as many levels of nested lists you need or want.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search