Sitemap
Zubeyr Anwar

Zubeyr Anwar

Front end developer at GebetaMaps

Fixing a Stuck MUI Select Menu During React Router Navigation + Suspense

2 min readMay 19, 2026

--

I ran into a surprisingly annoying issue with Material UI’s Select component while navigating between routes in React.

The bug only happened on the first selection.

When selecting a menu item:

  • the route changed
  • the page suspended
  • a Suspense fallback rendered
  • and the Select menu stayed visually stuck open

It looked like MUI never finished closing the dropdown.

The Setup

I had something like this:

<Select value={workspace} onChange={handleWorkspaceChange}>
{workspaces.map((workspace) => (
<MenuItem key={workspace.url} value={workspace.url}>
{workspace.name}
</MenuItem>
))}
</Select>

And inside the change handler:

const handleWorkspaceChange = (e: SelectChangeEvent) => {
const value = e.target.value;
  setWorkspace(value);  navigate(`/dashboard${value}`);
};

Looks harmless.

But because navigation triggered a rerender + Suspense fallback immediately, the Select component unmounted before MUI completed its internal close cycle.

The result:

  • backdrop remained
  • menu portal stayed mounted
  • dropdown appeared stuck open

Only on the first interaction.

Why This Happens

MUI Select uses:

  • a portal
  • internal open state
  • transition lifecycle events

When React Router navigation immediately triggers:

  • Suspense
  • rerender
  • unmount

…the Select never gets to properly fire its close lifecycle.

So the menu portal survives briefly in an inconsistent state.

The Wrong Fixes I Tried

I tried:

  • blur()
  • refs
  • setTimeout
  • requestAnimationFrame
  • checking previous values
  • memoization
  • useCallback

Some reduced the issue but none fully solved it.

Get Zubeyr Anwar’s stories in your inbox

Join Medium for free to get updates from this writer.

Because the real issue was timing.

The Real Fix

The solution was simple:

Do NOT navigate inside onChange

Instead:

  1. store the pending value
  2. close the Select first
  3. navigate only after onClose

Working Solution

const [open, setOpen] = useState(false);
const pendingWorkspaceRef = useRef<string | null>(null);const handleWorkspaceChange = useCallback(
(e: SelectChangeEvent) => {
const value = e.target.value;
if (value === workspace) return; // store pending navigation
pendingWorkspaceRef.current = value;
// update local state
setWorkspace(value);
// close menu first
setOpen(false);
},
[workspace],
);
const handleClose = useCallback(() => {
setOpen(false);
const pending = pendingWorkspaceRef.current; if (!pending) return; pendingWorkspaceRef.current = null; // wait until menu fully closes
requestAnimationFrame(() => {
navigate(`/dashboard${pending}`);
});
}, [navigate]);

Then wire it up:

<Select
open={open}
onOpen={() => setOpen(true)}
onClose={handleClose}
value={workspace}
onChange={handleWorkspaceChange}
>
{workspaces.map((workspace) => (
<MenuItem key={workspace.url} value={workspace.url}>
{workspace.name}
</MenuItem>
))}
</Select>

Why This Works

The flow becomes:

  1. User selects item
  2. Selection state updates
  3. Select closes normally
  4. onClose fires
  5. Navigation happens afterward

This allows MUI to clean up:

  • portal
  • backdrop
  • transitions
  • focus management

before Suspense remounts the tree.

Final Thoughts

This was one of those bugs where:

  • the UI looked broken
  • the logic looked correct
  • and the actual problem was component lifecycle timing

If you’re using:

  • MUI Select
  • React Router
  • Suspense/lazy routes

…and your dropdown gets stuck during navigation, delaying route changes until onClose is a working workaround.

--

--

Zubeyr Anwar
Zubeyr Anwar