[React 19] infinite re-render when `setFloating` is paired with `DropdownMenuTrigger` + `useOptimistic`
Author: branxyCreated Nov 27, 2025Updated Mar 5, 2026
LabelsNEEDS: triage
It is an issue involving an external library but it seems serious enough to be considered.
Floating dropdown menu. When setFloating is placed as a ref callback on DropdownMenuTrigger (RadixUI) or it's direct child, a call to setOptimistic inside DropdownMenuItem's onSelect causes an infinite re-render loop.
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button ref={refs.setFloating}>Open dropdown</button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
onSelect={() => {
startTransition(() => {
setStateOptimistic([]);
});
}}
>
Call setStateOptimistic()
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>The bug occurs only when both these 2 conditions meet:
- A
useOptimistichook is used AND an object is returned from its'updateFn.- works fine when
useStatewith objects is used instead ofuseOptimistic. - works fine when primitive values are returned from
useOptimistic'supdateFninstead of objects.
- works fine when
- A
setFloatingref setter fromuseFloatingis placed on aDropdownMenuTriggeror it's' direct child when usingasChild.- merging refs (e.g. via
useMergeRefs) doesn't help - works fine when
setFloatingis removed fromDropdownMenuTriggeror it's child. - works fine when plain HTML element is used instead of Radix's
DropdownMenu.
- merging refs (e.g. via
- I get that it's not a bug per se: RadixUI and
useOptimisticare involved, but I would appreciate an advice on whether this behaviour is expected when making floating dropdowns, or how can it be fixed. - It's also weird to me that
useOptimistic'supdateFnjust keeps infinitely running even though thesetOptimisticcall doesn't repeat. - So far the only workaround I found is stuffing a dummy div inside the
DropdownMenuTrigger— it catches the radix ref, and it seems to fix the issue:
<DropdownMenuTrigger asChild>
{/* ↓ catches the radix ref */}
<div>
{/* ↓ catches the floating ref */}
<button ref={refs.setFloating}>Open dropdown</button>
</div>
</DropdownMenuTrigger>Reproduction
React sandbox: https://codesandbox.io/p/devbox/78mrty?migrateFrom=ygxc37
Steps:
- Click "Open dropdown".
- Click "call
setStateOptimistic()". - See error in console.
Expected behavior
No infinite re-renders.
Context:
- Browser: Chrome
- Version: "@floating-ui/[email protected]", "[email protected]"
Source: floating-ui/floating-ui