0
votes

Like a lot of folks, our React-Bootstrap hamburger icon expands just fine, but when one of the links is selected, the nav menu remains expanded. Apparently, this might have something to do with React-Router edits that happened long before I started working on this code, but none of the solutions I've seen work for this issue.

I tried using a hook to fire off click handlers on the links to no avail. Also, putting expanded/collapsed in state didn't work out (unless I did it wrong). Does anyone know a fix for this? Thanks

This is the NavBar

class BSNavbar extends React.Component {
  constructor(props) {
    super(props)
    this.state = { supportModal: false, loginModal: false, infoPanel: false }
    this.loginModal = this.loginModal.bind(this)
    this.supportModal = this.supportModal.bind(this)
  }

  loginModal(open = true) {
    this.setState({ loginModal: open })
  }

  supportModal(open = true) {
    this.setState({ supportModal: open })
  }

  infoModal(open = true) {
    this.setState({ infoPanel: open })
  }

  render() {
    return (
      <>
        <Navbar collapseOnSelect>
          <Navbar.Header>
            <Navbar.Brand>
              <WebsiteBrandIcons />
            </Navbar.Brand>
            <Navbar.Toggle />
          </Navbar.Header>
          <Navbar.Collapse>
            <NavMenu
              loginModal={this.loginModal}
              supportModal={this.supportModal}
            />
          </Navbar.Collapse>
        </Navbar>
        <NavbarSpacer />
        {this.state.supportModal && (
          <Overlay>
            <ModalContainer>
              <ExitButton
                onClick={() => this.setState({ supportModal: false })}>
                &times;
              </ExitButton>
              <h3>Support</h3>
              <FreshdeskWidget />
            </ModalContainer>
          </Overlay>
        )}
        <LoginModal
          show={this.state.loginModal}
          modalToggle={this.loginModal.bind(this)}
          min={true}
        />
      </>
    )
  }
}

This is the NavMenu component of the NavBar (where the links are)

const FaqLink = ({ faq }) => {
  if (faq && faq.length) {
    return (
      <NavLink className="nav-link" to="/faq">
        <span className="link-name">faq</span>
      </NavLink>
    )
  } else {
    return null
  }
}

const SupportLink = ({ supportModal }) => {
  if (config.support.url) {
    return (
      <li className="link-support">
        <a className="nav-link" onClick={() => supportModal()}>
          <span className="link-name">Support</span>
        </a>
      </li>
    )
  } else {
    return null
  }
}

const NavMenu = ({ supportModal, loginModal }) => {
  return (
    <ul className="nav navbar-nav main-nav">
      <li className="link-dashboard">
        <LoggedIn>
          <NavLink className="nav-link" to="/dashboard/datasets">
            <span className="link-name">My Dashboard</span>
          </NavLink>
        </LoggedIn>
      </li>
      <li className="link-public">
        <NavLink className="nav-link" to="/public/datasets">
          <span className="link-name">Public Dashboard</span>
        </NavLink>
      </li>
      <SupportLink supportModal={supportModal} />
      <li className="link-faq">
        <FaqLink faq={faq} />
      </li>
        <li className="link-dashboard">
          <LoggedIn>
            <UploaderView />
          </LoggedIn>
        </li>
      <li>
        <Navbar.Collapse>
          <Usermenu />
          <LoggedOut>
            <div className="navbar-right sign-in-nav-btn">
              <button className="btn-blue" onClick={() => loginModal()}>
                <span>Sign in</span>
              </button>
            </div>
          </LoggedOut>
        </Navbar.Collapse>
      </li>
    </ul>
  )
}
1

1 Answers

0
votes

Okay, so here's my solution:

class BSNavbar extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      supportModal: false,
      loginModal: false,
      infoPanel: false,
      navExpanded: false, //new 
    }
    this.loginModal = this.loginModal.bind(this)
    this.supportModal = this.supportModal.bind(this)
//new 
    this.setNavExpanded = this.setNavExpanded.bind(this)
    this.closeNav = this.closeNav.bind(this)
  }

  loginModal(open = true) {
    this.setState({ loginModal: open })
  }

  supportModal(open = true) {
    this.setState({ supportModal: open })
  }

  infoModal(open = true) {
    this.setState({ infoPanel: open })
  }

//new 
  setNavExpanded(expanded = true) {
    this.setState({ navExpanded: expanded })
  }

//new 
  closeNav() {
    this.setState({ navExpanded: false })
  }


  render() {
    return (
      <>
        <Navbar
          onToggle={this.setNavExpanded}
          expanded={this.state.navExpanded}>
          <Navbar.Header>
            <Navbar.Brand>
              <WebsiteBrandIcons />
            </Navbar.Brand>
            <Navbar.Toggle />
          </Navbar.Header>
          <Navbar.Collapse>
            <NavMenu
              closeNav={this.closeNav}
              loginModal={this.loginModal}
              supportModal={this.supportModal}
            />
          </Navbar.Collapse>
        </Navbar>
        ...
const NavMenu = ({ supportModal, loginModal, closeNav }) => {
  return (
    <ul className="nav navbar-nav main-nav">
      <li className="link-dashboard">
        <LoggedIn>
          <NavLink
            onClick={closeNav}
            className="nav-link"
            to="/dashboard/datasets">
            <span className="link-name">My Dashboard</span>
          </NavLink>
        </LoggedIn>
      </li>
      <li className="link-public">
        <NavLink onClick={closeNav} className="nav-link" to="/public/datasets">
          <span className="link-name">Public Dashboard</span>
        </NavLink>
      </li>
      <SupportLink closeNav={closeNav} supportModal={supportModal} />
      <li className="link-faq">
        <FaqLink closeNav={closeNav} faq={faq} />
      </li>
      <li className="link-admin">
        <AdminLink closeNav={closeNav} />
      </li>
        <li className="link-dashboard">
          <LoggedIn>
            <UploaderView />
          </LoggedIn>
        </li>
      <li>
        <Navbar.Collapse>
          <Usermenu closeNav={closeNav} />
          <LoggedOut>
            <div className="navbar-right sign-in-nav-btn">
              <button className="btn-blue" onClick={() => loginModal()}>
                <span>Sign in</span>
              </button>
            </div>
          </LoggedOut>
        </Navbar.Collapse>
      </li>
    </ul>
  )
}

I just made sure the props were passed down where needed. I think this is a decent interim solution, but would like to rebuild the Navbar completely eventually (mostly to get rid of Bootstrap).

Hope this helps someone out there...