You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a tree contains all of the following, any mouse movement after mount throws Maximum update depth exceeded and blanks the page:
<DropZone> (react-aria-components)
An S2 <Button> whose child is a string/<Text>
A controlled <Tabs> (selectedKey + onSelectionChange)
A <Skeleton isLoading> containing <Text>, inside a <TabPanel>
Take any one of those away and the bug disappears. The initial render is clean, the loop starts on the first pointermove after mount. Reproduces in dev (Vite + StrictMode) and in production builds.
🤔 Expected Behavior?
Moving the mouse over a page that happens to contain a <DropZone> ancestor of a <Button>, <Tabs>, and <Skeleton> shouldn't kill the page.
😯 Current Behavior
The page renders fine on first paint. The moment the mouse moves anywhere in the element, React throws:
Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
at getRootForUpdatedFiber
at enqueueConcurrentHookUpdate
at dispatchSetStateInternal
at dispatchSetState
at <anonymous frame inside a react-aria hook>
at commitHookEffectListMount
at commitHookPassiveMountEffects
at commitPassiveMountOnFiber
Component stack at the point of failure:
<ForwardRef(DropZone)><App>
React DevTools' "Highlight updates when components render" shows <Text> flashing at the highest frequency, with the surrounding Button, internal Tabs components, and the page root flashing one revision behind.
A few things Claude and I checked along the way that turned out not to be the cause, in case they save someone time:
Initially suspected the useIdsetValue(newId) path in @react-aria/utils (the #7655 regression via PR #7757). I added a breakpoint on that line but newId is always null, the setter never fires. So whatever hook is looping, it isn't that setValue.
I also checked the @react-stately/utils@3.11.0useControlledState regression (#9420) by pinning to 3.10.8 via a pnpm override. Bug still reproduces.
The loop is reproducible in both:
Vite dev server with React Fast Refresh + StrictMode
vite build + vite preview production bundle (no HMR, no StrictMode double-invoke)
💁 Possible Solution
I couldn't pin down the exact setter, but the strongest suspect from the static analysis is useValueEffect in @react-aria/utils. Its inner useLayoutEffect runs on every render with no deps:
If a downstream consumer (e.g. useSlotId's document.getElementById(id) ? id : undefined generator) keeps producing a different value across renders, setValue is called every commit and never settles. A same-value guard inside nextRef.current() (or a deps array on the useLayoutEffect) may break the cycle...?
Provide a general summary of the issue here
When a tree contains all of the following, any mouse movement after mount throws
Maximum update depth exceededand blanks the page:<DropZone>(react-aria-components)<Button>whose child is a string/<Text><Tabs>(selectedKey+onSelectionChange)<Skeleton isLoading>containing<Text>, inside a<TabPanel>Take any one of those away and the bug disappears. The initial render is clean, the loop starts on the first
pointermoveafter mount. Reproduces in dev (Vite + StrictMode) and in production builds.🤔 Expected Behavior?
Moving the mouse over a page that happens to contain a
<DropZone>ancestor of a<Button>,<Tabs>, and<Skeleton>shouldn't kill the page.😯 Current Behavior
The page renders fine on first paint. The moment the mouse moves anywhere in the element, React throws:
Component stack at the point of failure:
React DevTools' "Highlight updates when components render" shows
<Text>flashing at the highest frequency, with the surroundingButton, internal Tabs components, and the page root flashing one revision behind.A few things Claude and I checked along the way that turned out not to be the cause, in case they save someone time:
useIdsetValue(newId)path in@react-aria/utils(the #7655 regression via PR #7757). I added a breakpoint on that line butnewIdis alwaysnull, the setter never fires. So whatever hook is looping, it isn't thatsetValue.@react-stately/utils@3.11.0useControlledStateregression (#9420) by pinning to3.10.8via a pnpm override. Bug still reproduces.The loop is reproducible in both:
vite build+vite previewproduction bundle (no HMR, no StrictMode double-invoke)💁 Possible Solution
I couldn't pin down the exact setter, but the strongest suspect from the static analysis is
useValueEffectin@react-aria/utils. Its inneruseLayoutEffectruns on every render with no deps:If a downstream consumer (e.g.
useSlotId'sdocument.getElementById(id) ? id : undefinedgenerator) keeps producing a different value across renders,setValueis called every commit and never settles. A same-value guard insidenextRef.current()(or a deps array on theuseLayoutEffect) may break the cycle...?🔦 Context
No response
🖥️ Steps to Reproduce
pnpm(doubt if that's relevant or not but it's my environment)pnpm install,pnpm dev.Maximum update depth exceeded. Page blanks.Variants that do not trigger the crash (all four conditions are required):
<Tabs>(dropselectedKey/onSelectionChange).<Skeleton>withoutisLoading.<Button><span>Sign in</span></Button>(bypasses the implicit<Text>wrap).<DropZone>with a plain<div>Packages
@react-spectrum/s2@1.3.1react-aria-components@1.17.0@react-aria/utils@3.33.0@react-stately/utils@3.10.8(pinned via pnpm override; bug still reproduces; confirms this is unrelated to @react-stately/utils@3.11.0 triggers rerender loop #9420)react@19.2.4/react-dom@19.2.4Version
1.3.1
What browsers are you seeing the problem on?
Chrome
If other, please specify.
No response
What operating system are you using?
MacOS 26.3.1 (Tahoe)
🧢 Your Company/Team
Adobe/Incubator
🕷 Tracking Issue
No response