React-Bootstrap Navbar Won't Collapse: A Diagnostic Guide for v2.x
A diagnostic guide for a React-Bootstrap 2.x Navbar whose toggler won't open or close the menu: version checks, structure, CSS conflicts, controlled state, and escalation criteria.
03 Jul 2025, 08:55 UTC

Your React-Bootstrap Navbar renders fine, but the hamburger toggler does nothing when clicked — or the menu opens and refuses to close after you tap a link. This is one of the most common React-Bootstrap complaints, and it almost always comes down to one of five causes: a version mismatch, a missing expand prop, broken structure, conflicting CSS, or a silent JavaScript error. This guide walks through each cause, how to confirm it, and the fix that matches.
Assumptions: react-bootstrap 2.x with Bootstrap 5 CSS. In Bootstrap 5, data attributes are namespaced as data-bs-*, and react-bootstrap 2.x handles the toggle internally — you should not need jQuery or bootstrap.js at all.
Symptom-to-cause table
| Symptom | Likely cause | First check |
|---|---|---|
| Toggler click does nothing at all | Version mismatch or missing expand prop | Installed versions of react-bootstrap and bootstrap |
| Menu never collapses on small screens (always stacked) | Missing expand prop or Navbar.Collapse wrapper | Component structure |
| Menu opens but stays open after clicking a link | Collapse state not tied to navigation | Whether you control expanded yourself |
| Animation stutters or menu snaps open/closed | Custom CSS overriding .collapsing or overflow: hidden on a parent | DevTools element inspection |
| Nothing works and the console shows an error | JS error aborting React event handling | Browser console |
Check 1: Match react-bootstrap and Bootstrap CSS versions
react-bootstrap 2.x is built for Bootstrap 5 markup. Pairing it with Bootstrap 4 CSS (or vice versa) produces a navbar whose classes exist but whose collapse behavior is broken, because the class names and data attributes differ between major versions. Run this in your project root:
npm ls react-bootstrap bootstrapYou want react-bootstrap@2.x alongside bootstrap@5.x. If you see bootstrap@4.x, upgrade it (npm install bootstrap@5) and retest before going further — mismatched versions account for a large share of "toggler does nothing" reports. Also confirm you actually import the CSS once, typically in your entry file:
import 'bootstrap/dist/css/bootstrap.min.css';Check 2: Verify the component structure
The collapse behavior in react-bootstrap is wired together by three pieces: the expand prop on Navbar, a Navbar.Toggler, and a Navbar.Collapse wrapping your Nav. Leave out any one of them and the toggle silently stops working. A correct minimal structure:
import { Navbar, Nav, Container } from 'react-bootstrap';
function SiteNav() {
return (
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand href="/">My App</Navbar.Brand>
<Navbar.Toggler aria-controls="main-nav" />
<Navbar.Collapse id="main-nav">
<Nav className="me-auto">
<Nav.Link href="/docs">Docs</Nav.Link>
<Nav.Link href="/about">About</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}Two details matter here. First, expand="lg" tells the navbar to collapse below the lg breakpoint; without it the menu never collapses and the toggler never appears. Second, the aria-controls on the toggler must match the id on Navbar.Collapse — react-bootstrap uses that pairing to know which element to toggle. Open your browser DevTools, inspect the rendered button, and confirm it carries aria-controls pointing at an existing element's id.
Check 3: Look for console errors
An uncaught error anywhere in the click path — for example in an onClick handler you attached to a Nav.Link — can prevent React from completing the event dispatch, leaving the collapse state untouched. Open DevTools (F12 in Chrome/Edge/Firefox), click the toggler, and watch the console. Any red error at click time is your prime suspect; fix it first and retest. React warnings about keys or invalid DOM nesting (such as putting a <div> inside a <p>) are worth cleaning up too, but they rarely break the toggle by themselves.
Check 4: Rule out CSS conflicts
Bootstrap animates collapse by toggling a .collapsing class that sets height: 0 and a transition. Custom CSS that overrides this — a global * { transition: none }, an overflow: hidden on the navbar's parent, or a rule forcing .collapse { display: block !important } — will break the animation or hide the expanded menu. To isolate this, temporarily render the navbar alone in a fresh route with no custom stylesheets beyond Bootstrap's. If it works there, bisect your CSS: comment out half your custom rules, retest, and narrow down. In DevTools, select the collapsing element and look in the Styles pane for any of your rules overriding height, display, or transition on .collapsing or .navbar-collapse.
Check 5: Closing the menu after navigation
A frequent complaint is not that the toggle fails, but that the menu stays open after the user taps a link in a single-page app. The fix is to control the expanded state yourself and collapse it on navigation:
import { useState } from 'react';
import { Navbar, Nav, Container } from 'react-bootstrap';
function SiteNav() {
const [expanded, setExpanded] = useState(false);
return (
<Navbar
bg="light"
expand="lg"
expanded={expanded}
onToggle={(next) => setExpanded(next)}
>
<Container>
<Navbar.Brand href="/">My App</Navbar.Brand>
<Navbar.Toggler aria-controls="main-nav" />
<Navbar.Collapse id="main-nav">
<Nav className="me-auto">
<Nav.Link href="/docs" onClick={() => setExpanded(false)}>
Docs
</Nav.Link>
<Nav.Link href="/about" onClick={() => setExpanded(false)}>
About
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}If you use React Router, an alternative is calling setExpanded(false) inside a route-change effect instead of on every link. Verify the state is actually flipping with React DevTools: select the Navbar component and watch the expanded prop toggle as you click.
A note on server-side rendering
If you render with Next.js or another SSR framework, a mismatch between the server-rendered markup and the client's initial state can leave the collapse in a stuck state after hydration. Keep the initial expanded value deterministic (usually false) and only change it in response to client-side events. If you must derive it from something client-only like viewport width, set it in a useEffect so the first client render matches the server HTML.
How to verify the fix
- Resize the browser below the
lgbreakpoint (or use DevTools device emulation) so the toggler appears. - Click the toggler: the menu should animate open; click again to close.
- Click a link while open: with the controlled-state fix, the menu should close.
- Confirm the console stays clean through all of the above.
- If possible, reproduce the original failure in a fresh Create React App (or Vite) project with only react-bootstrap and bootstrap installed — if the fresh project works, the problem is in your app's code or CSS, not the library.
When to escalate
Consider filing an issue on the react-bootstrap GitHub repository only when all of the following hold: versions are aligned, the minimal structure above fails in a fresh project with no custom CSS, the console is clean, and the problem reproduces in more than one browser. Include a minimal CodeSandbox reproduction, your exact react-bootstrap and bootstrap versions, and the browser version. If the fresh project works but your app doesn't, the issue belongs in your codebase — keep bisecting CSS and component structure rather than reporting upstream.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.