DEV Community

loading...
Cover image for How to toggle Bootstrap navbar collapse button in React without jQuery

How to toggle Bootstrap navbar collapse button in React without jQuery

johnotu profile image John Otu Updated on ・2 min read

Do you use Bootstrap (CSS) in React? You would've come across the advise not to add jQuery for good reason. jQuery directly manipulates the DOM so will be in conflict with React's virtual DOM which assumes it's the only Oga in charge.

But many cool Bootstrap components rely on jQuery and other Bootstrap JS plugins to work. One of such components is the navbar collapse toggle button and we can toggle it by dynamically adding (or removing) the collapse class in the nav-link's parent div.

Nav Toggle

<div class={`${isNavCollapsed ? 'collapse' : ''} navbar-collapse`} id="navbarsExample09">
  <a className="nav-link text-info" href="/contact">Support</a>
  <a className="nav-link text-info" href="/login">Login</a>
  <a href="/request-demo" className="btn btn-sm btn-info nav-link text-white" >Request demo</a>
</div>
Enter fullscreen mode Exit fullscreen mode

This seems to be the easiest way since we are still relying on Bootstrap CSS classes rather than write our own toggle functon from scratch. Using Hooks for state management and not forgetting aria-expanded boolean, we can have a TopNav component like:

import React, { useState } from 'react';
import Logo from '../images/logo_512x512.png';

const TopNav = props => {
  const [isNavCollapsed, setIsNavCollapsed] = useState(true);

  const handleNavCollapse = () => setIsNavCollapsed(!isNavCollapsed);

  return (
    <nav class="navbar navbar-expand-lg navbar-light bg-light rounded">
      <a class="navbar-brand text-info font-weight-bolder" href="/">
        <img src={Logo} alt="Logo" width="36" height="36" className="vertical-align-middle" />
        <span className="">Discounter</span>
      </a>
      <button class="custom-toggler navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample09" aria-controls="navbarsExample09" aria-expanded={!isNavCollapsed ? true : false} aria-label="Toggle navigation" onClick={handleNavCollapse}>
        <span class="navbar-toggler-icon"></span>
      </button>

      <div class={`${isNavCollapsed ? 'collapse' : ''} navbar-collapse`} id="navbarsExample09">
        <a className="nav-link text-info" href="/contact">Support</a>
        <a className="nav-link text-info" href="/login">Login</a>
        <a href="/request-demo" className="btn btn-sm btn-info nav-link text-white" >Request demo</a>
      </div>
    </nav>
  );
}

export default TopNav;
Enter fullscreen mode Exit fullscreen mode

Easy peasy right?

Discussion (4)

pic
Editor guide
Collapse
dmikester1 profile image
Mike Dodge • Edited

This works to do a basic show/hide. But it doesn't give you that nice slide down and up effect that Bootstrap does. I'm on Bootstrap 5. It appears like they(Bootstrap) are adding collapsing as it's moving and that removing that class and adding show when it's done.

Collapse
johnotu profile image
John Otu Author

Bootstrap animations are powered by the JS file which we've not added in our use case. However you can implement CSS transitions and animations in React using React Transitions Group.

Substituting the appropriate class for the version of Bootstrap you are using should give the desired results.

Collapse
yaezah profile image
yaezah

Thanks for this. Would it work the same way with Bootstrap 5 since it doesn't use jQuery? I tried to append a collapsable element using useEffect in react, but that didn't work for me.

Collapse
johnotu profile image
John Otu Author

Sorry about the late reply.

Yes it should work the same way with Bootstrap 5 with appropriate classes.

I tried to append a collapsable element using useEffect in react, but that didn't work for me.

I don't fully understand what you mean here. Could you maybe drop a snippet?