program nav menu in react. How do I use logical statements to display html?

Viewed 98

I'm using gatsby.js to make a site and using graphql to pull in data for a menu. The menu data is working fine however when I try to add a submemu with logical conditions it outputs the html instead of rendering it. So instead of showing the unordered submenu list, it outputs <ul> and </ul> on my site. (where the list items and main ul are working fine)

Here is my menu component code:

const WPMenu = () => (
  <StaticQuery
    query ={ graphql`
    {
      wordpressMenusMenusItems(name: {eq: "Main Menu"}) {
        name
        items {
          slug
          title
          child_items {
            slug
            title
          }
        }
      }
    }`
    }
    render = { data => (
      <nav role="navigation">
        <ul>
          {data.wordpressMenusMenusItems.items.map(item => (
            <li key={item.title}>
              {item.child_items ? <Link aria-haspopup="true" to={`/${item.slug}`}>{item.title}</Link> : <Link to={`/${item.slug}`}>{item.title}</Link>}
              {item.child_items ? '<ul>' : "" } //this line is not working
              {item.child_items && item.child_items.map ( child => 
                  <li key={child.title}><Link to={`/${child.slug}`} >{child.title}</Link></li>
              )}
              {item.child_items ? '</ul>' : "" }  //this line is not working
            </li>
          ))}
        </ul>
      </nav>
    )}
  />
);

its the two commented lines {item.child_items ? '<ul>' : "" } //this line is not working That are giving me problems.

I've tried with this: {item.child_items ? "<ul>" : "" }

and replacing quotes with code ticks as well:

{item.child_items ? `<ul>` : "" }

I'm new to js, so likely there's something I'm missing, but why is it interpreting it as code?

1 Answers

The problem is that is item.child_items is true if is an empty array [] since it is checking it reference exist or not; you can use item.child_items.length > 0 as the condition or simply item.child_items.lengthsince 0 is equal to false in js 0 == false //true

{item.child_items.length && '<ul>'}

or

{item.child_items.length > 0 ? '<ul>' : ''}

check the snippet for more info:

const obj = { items : [] }

//even though it is empty it will give you true;
console.log( Boolean(obj.items) )
// not not something is boolean equivilant of that thing
console.log( !!obj.items )

//workaround? using length
//since 0 == false
console.log( "how about length?", Boolean(obj.items.length))

Caveat: if item.child_items doesn't have length property, that line would throw an exception (e.g. item.child_items being undefined or null)

Related