0

I am trying to traverse through my array to get a specific object nested inside of it.

Some objects contain a children property, which should be traversed until a matching object is found.

Here's some example data, I am trying to obtain the object with id as 4

const items = [{
    id: 1,
    title: 'Title for Item 1'
  },
  {
    id: 2,
    title: 'Title for Item 2',
    children: [
        { 
        id: 3,
        title: "Title for Item 3",
        children: [
            {
            id: 4,
            title: "Title for Item 4",
          }
        ]
      }
    ]
  },
]

I've written some traversal code but it returns undefined.

const items = [{
    id: 1,
    title: 'Title for Item 1'
  },
  {
    id: 2,
    title: 'Title for Item 2',
    children: [
        { 
        id: 3,
        title: "Title for Item 3",
        children: [
            {
            id: 4,
            title: "Title for Item 4",
          }
        ]
      }
    ]
  },
]

const getItem = (items) => {
  if (!items) return;
  const item = items && items.find(i => i.id === 4);
  if (!item) {
    items.forEach(i => {
      return getItem(i.children)
    })
    // This is where undefined is returned
  } else {
    console.log({
      item
    }) // Prints the correct object.
    return item;
  }
};


const s = getItem(items); // undefined

document.querySelector('#foo').textContent = s ? s : 'undefined';
<div id="foo"></div>

1
  • You should tag this question with javascript to attract the right audience. Commented Aug 8, 2018 at 19:25

1 Answer 1

1

At least two issues explain why it does not work:

  1. A return statement in a forEach callback will return the returned value to nowhere. Nothing happens with it.
  2. The result of the recursive call is not checked. It needs to be checked to see if it is defined. Depending on that you can decide whether to continue the loop or exit from it.

Replace that forEach with a for...of loop so you can return "out of it", but only do that when you have a match, otherwise you need to continue the loop:

for (const item of items) {
    const match = getItem(item.children);
    if (match) return match;
}

Note that in your snippet you should not set the textContent to the return value, as that is an object and will get converted to the string "[Object object]". You could for instance just grab the title string and put that in textContent:

const items = [{
    id: 1,
    title: 'Title for Item 1'
  },
  {
    id: 2,
    title: 'Title for Item 2',
    children: [
        { 
        id: 3,
        title: "Title for Item 3",
        children: [
            {
            id: 4,
            title: "Title for Item 4",
          }
        ]
      }
    ]
  },
]

const getItem = (items) => {
  if (!items) return;
  const item = items && items.find(i => i.id === 4);
  if (!item) {
    for (const item of items) {
        const match = getItem(item.children);
        if (match) return match;
    }
  } else {
    console.log({
      item
    }) // Prints the correct object.
    return item;
  }
};


const s = getItem(items); // undefined

document.querySelector('#foo').textContent = s ? s.title : 'undefined';
<div id="foo"></div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.