简体   繁体   中英

React Recursive Function to Render Components

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.

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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM