Bootstrap Navbar Collapse in ReactJS



Bootstrap is an amazing library and works wonders with ReactJS. Unfortunately, you can’t (or really shouldn’t) use Bootstrap.js with React because bootstrap directly manipulates the DOM; which could break React’s nice rendering flow. This becomes a big problem if you wanted to implement a Navbar using plain bootstrap. Take the following for example from Bootstrap’s documentation:

 

You could directly take this code and put it in ReactJS (but change class _to _className) and you will have a working Navbar. If you tried viewing this on mobile then you sill get the following:

 

Nothing wrong right? This is perfectly expected behavior. The only problem is that if you click on the navbar collapse hamburger button, nothing will happen. This is because you need to use Bootstrap.js to change the class, which you’re not using because you shouldn’t mix Bootstrap.js and React. So one solution is to use a bootstrap library built directly for Reactjs. However, I hate this idea because I don’t need a whole library for something I could easily fix. So let’s take a look at how to do it.

Bootstrap Navbar Collapse in ReactJS

In order make the Navbar appear when the toggle button is selected, we just need to add a class to the Navbar and an onClick handler to the button. Bootstrap.css takes care of the visibility. Here is the entire code of my Navbar.js component I created:

import React, { Component } from 'react';
 import { Link } from 'react-router-dom';

class Nav extends Component {
 constructor(props) {
 super(props);
 this.toggleNavbar = this.toggleNavbar.bind(this);
 this.state = {
 collapsed: true,
 };
 }
 toggleNavbar() {
 this.setState({
 collapsed: !this.state.collapsed,
 });
 }
 render() {
 const collapsed = this.state.collapsed;
 const classOne = collapsed ? 'collapse navbar-collapse' : 'collapse navbar-collapse show';
 const classTwo = collapsed ? 'navbar-toggler navbar-toggler-right collapsed' : 'navbar-toggler navbar-toggler-right';
 return (
 <nav className="navbar navbar-expand-lg navbar-dark bg-dark transparent-nav">
 <div className="container">
 <a className="navbar-brand" href="#">Rate My Neighborhood</a>
 <button onClick={this.toggleNavbar} className={`${classTwo}`} type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
 <span className="navbar-toggler-icon" />
 </button>
 <div className={`${classOne}`} id="navbarResponsive">
 <ul className="navbar-nav ml-auto">
 <li className="nav-item active">
 <Link className="nav-link" to="/">Home</Link>
 </li>
 <li className="nav-item">
 <Link className="nav-link" to="/about">About</Link>
 </li>
 </ul>
 </div>
 </div>
 </nav>
 );
 }
 }
export default Nav;

In the component’s state, I defined a collapse boolean. Then in the render function, I check to see if the collapsed component is true. If it is, I change the class of the navbarResponsive div. In addition, if collapse is true, then I also have to change the class of the button. Here are the relevant pieces of code:

const collapsed = this.state.collapsed;
 const classOne = collapsed ? 'collapse navbar-collapse' : 'collapse navbar-collapse show';
 const classTwo = collapsed ? 'navbar-toggler navbar-toggler-right collapsed' : 'navbar-toggler navbar-toggler-right';
 return (
 <nav className="navbar navbar-expand-lg navbar-dark bg-dark transparent-nav">
 <div className="container">
 <a className="navbar-brand" href="#">Rate My Neighborhood</a>
 <button onClick={this.toggleNavbar} className={`${classTwo}`} type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
 <span className="navbar-toggler-icon" />
 </button>
 <div className={`${classOne}`} id="navbarResponsive">

Keep in mind that conditional rendering in ReactJS requires use of the conditional (ternary) operator (the question mark).

Finally, I declare a function that changes the state of the collapsed boolean when the collapse button is clicked:

toggleNavbar() {
this.setState({
collapsed: !this.state.collapsed,
});
}

That’s it! Now when you view the navbar on mobile and click on the collapse button, your navbar will appear as normal.

View the code on GitHub