0

I've been attempting to render a react-bootstrap component within a custom navBar component in react. I have a recursive function set up which is supposed to run in react render and drill down until there are no nav Item components under the NavDropDown Components. Currently when any attempts at drilling down return as undefined and don't display in the nav bar.

I've tried reformatting my react code in numerous ways, including/removing brackets, switching to plaintext, etc.

code below:

navContent = {[

                {
                type : "link",
                target: "/",
                content: "Home"
                },
                {
                type: "dropdown",
                  title: "CLICK ME",
                  content: [
                    {type : "item",
                    target: "/",
                    content: "home"
                  },
                  {type : "item",
                  target: "/",
                  content: "home"
                  }
                  ]
                },
                {
                type: "form",
                formType: "text",
                placeholder: "search",
                className: "",
                buttonType: "submit",
                buttonContent: "Submit"
                },

              ]}

export default class Navigation extends React.Component {

  constructor(props){
    super(props);
    this.state = {
    }
  }





getNavItem(navItem){
  switch(navItem.type){
    case 'link':
      return <Nav.Link><Link to={navItem.target}>{navItem.content}</Link></Nav.Link>
    case 'dropdown':
      return <NavDropdown id="basic-nav-dropdown" title={navItem.title}>
                {navItem.content.map(item => {this.getNavItem(item)})}
             </NavDropdown>
    case 'form':
      return  <Form inline> <FormControl type={navItem.formType} placeholder={navItem.placeholder} className={navItem.className}/><Button type={navItem.buttonType}>{navItem.buttonContent}</Button></Form>
    case 'item':
      return <NavDropdown.Item><Link to={navItem.target}>{navItem.content}</Link></NavDropdown.Item>

  }
}

render(

){
  return(
    <Navbar bg="light" expand="lg">
      <Link to="/"><Navbar.Brand>Home Placeholder</Navbar.Brand></Link>
      <Navbar.Toggle aria-controls="basic-navbar-nav" />
      <Navbar.Collapse id="basic-navbar-nav">
        <Nav className="mr-auto">
          {this.props.navContent.map(navItem => this.getNavItem(navItem))}
        </Nav>
      </Navbar.Collapse>
    </Navbar>
  )
}
}

Ideally when the case switch hits dropdown in the getNavItem function it should run the function again iterating down into the content key of the dropdown object and render both objects inside of it under the dropdown. Currently the dropdown content doesn't render.

1
  • It's time to go "maybe I wrote the wrong code", so start without any children. Does <Nav> render correctly now? If not, it's not infinitely easier to debug your code in terms of where things might have gone wrong. Does it work? Cool: add a single child, and see what happens Commented Aug 14, 2019 at 23:14

1 Answer 1

1

You're not returning the result in this map {navItem.content.map(item => {this.getNavItem(item)})}. Should be {navItem.content.map(item => this.getNavItem(item))} or {navItem.content.map(item => { return this.getNavItem(item)})}. See below example (I replaced your components with divs but the structure is right):

const navContent = [
  {
    type: "link",
    target: "/",
    content: "Home"
  },
  {
    type: "dropdown",
    title: "CLICK ME",
    content: [
      { type: "item", target: "/", content: "home" },
      { type: "item", target: "/", content: "home" }
    ]
  },
  {
    type: "form",
    formType: "text",
    placeholder: "search",
    className: "",
    buttonType: "submit",
    buttonContent: "Submit"
  }
];

class Navigation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  getNavItem(navItem) {
    const foo = () => 1;
    switch (navItem.type) {
      case "link":
        return (
          <div className="Nav.Link">
            <div className="Link" to={navItem.target}>
              {navItem.content}
            </div>
          </div>
        );
      case "dropdown":
        return (
          <div
            className="NavDropdown"
            id="basic-nav-dropdown"
            title={navItem.title}
          >
            {navItem.content.map((item) => this.getNavItem(item))}
          </div>
        );
      case "form":
        return (
          <div className="Form" inline>
            {" "}
            <div
              className="FormControl"
              type={navItem.formType}
              placeholder={navItem.placeholder}
              className={navItem.className}
            />
            <div className="Button" type={navItem.buttonType}>
              {navItem.buttonContent}
            </div>
          </div>
        );
      case "item":
        return (
          <div className="NavDropdown.Item">
            <div className="Link" to={navItem.target}>
              {navItem.content}
            </div>
          </div>
        );
    }
  }

  render() {
    return (
      <div className="Navbar" bg="light" expand="lg">
        <div className="Link" to="/">
          <div className="Navbar.Brand">Home Placeholder</div>
        </div>
        <div className="Navbar.Toggle" aria-controls="basic-navbar-nav" />
        <div className="Navbar.Collapse" id="basic-navbar-nav">
          <div className="Navbar.Collapse mr-auto">
            {this.props.navContent.map(this.getNavItem.bind(this))}
          </div>
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <Navigation navContent={navContent} />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<Navigation/>
<div id="react"></div>

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

1 Comment

Thank you! This was killing me.

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.