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
React Aria Components collections (GridList, TabList, likely all collection components) render empty when their subtree is hidden via React 19.2 <Activity mode="hidden"> after having been visible and populated, and then shown again.
This is the scenario originally reported in #9319, which was closed as a duplicate of #9173 before the fix for #9173 (#9300) was merged. #9300 fixes the starts-hidden, first-reveal case, but the visible, then hidden, then visible-again case still reproduces on the latest release (1.19.0). As far as I can tell it is currently untracked.
This affects every Next.js 16 app using Cache Components: the Next router wraps up to 3 preserved routes in <Activity mode="hidden"> and re-shows the same instance on back-navigation (see Preserving UI state), so any collection component on a route breaks on every return visit.
🤔 Expected Behavior?
Items re-appear when the Activity boundary becomes visible again. The DOM and state were preserved, and the owning component re-renders with the correct items.
😯 Current Behavior
The collection renders empty. All GridListItem rows / Tab elements are gone from the DOM entirely (not merely hidden), while static siblings outside the collection render fine.
Things I verified while debugging:
The fix: collections nested within Activities (React 19.2) #9300 fix is present in the shipped react-aria-components@1.19.0 bundle. dist/private/collections/Document.mjs contains the patched queueUpdate (this.collection = this.collection.clone() before notifying subscriptions) and getCollection returning this.collection while inSubscription. So this is not a stale-dependency problem.
The props reaching the collection owner are correct on the broken render. I logged item counts on every render and commit; renders and commits both happen with the right data.
Forcing a single re-render after reveal fixes it. An effect that runs on the hide-to-visible transition (effects re-run on reveal) and bumps a useState restores all items without remounting:
functionuseRerenderOnActivityReveal(){const[,bump]=useState(0);constmounted=useRef(false);useEffect(()=>{if(!mounted.current){mounted.current=true;return;}bump((k)=>k+1);// re-shown after Activity hide},[]);}
This suggests the collection store repopulates during or after reveal but never schedules the render that would make useSyncExternalStore re-read it. That is the same class of problem #9300 fixed for the mount path, but on the reappear path.
I searched for later fixes: the only commits to Document.ts since fix: collections nested within Activities (React 19.2) #9300 are unrelated (a Tree refactor and package consolidation), no open issue or PR tracks this case, and no newer stable release exists.
💁 Possible Solution
Presumably the reveal path (reappearLayoutEffects: refs and effects re-attach, useSyncExternalStore resubscribes) needs the same "clone so React queues a render" treatment that #9300 applied to queueUpdate, or the store needs to schedule one render on resubscribe when its snapshot changed while hidden.
Happy to test a patch; we can reproduce this reliably.
🔦 Context
We hit this in a production dashboard after enabling Next.js 16 Cache Components. Every list and tab bar in the app disappears whenever a user navigates away from a page and back. We are shipping the re-render-on-reveal hook above as a temporary workaround in our shared component wrappers.
🖥️ Steps to Reproduce
Observed in a Next.js 16 app (cacheComponents: true), where the router drives the Activity boundaries:
Render a route containing a GridList (or Tabs) populated with items. Items render correctly.
Client-side navigate to another route. Next hides the previous route's tree in <Activity mode="hidden">; the DOM is preserved and effects are cleaned up.
Client-side navigate back. Next flips the preserved instance to mode="visible".
The GridList items / TabList tabs are gone from the DOM.
Equivalent pure-React shape (matches what the Next router does):
<Activitymode={show ? 'visible' : 'hidden'}><GridListaria-label="test"><GridListItem>One</GridListItem><GridListItem>Two</GridListItem></GridList></Activity>// start with show=true (items render), set show=false, then show=true again: items are gone
Note the difference from #9173's reproduction, which started hidden. The tests added in #9300 cover the starts-hidden case.
Provide a general summary of the issue here
React Aria Components collections (
GridList,TabList, likely all collection components) render empty when their subtree is hidden via React 19.2<Activity mode="hidden">after having been visible and populated, and then shown again.This is the scenario originally reported in #9319, which was closed as a duplicate of #9173 before the fix for #9173 (#9300) was merged. #9300 fixes the starts-hidden, first-reveal case, but the visible, then hidden, then visible-again case still reproduces on the latest release (1.19.0). As far as I can tell it is currently untracked.
This affects every Next.js 16 app using Cache Components: the Next router wraps up to 3 preserved routes in
<Activity mode="hidden">and re-shows the same instance on back-navigation (see Preserving UI state), so any collection component on a route breaks on every return visit.🤔 Expected Behavior?
Items re-appear when the Activity boundary becomes visible again. The DOM and state were preserved, and the owning component re-renders with the correct items.
😯 Current Behavior
The collection renders empty. All
GridListItemrows /Tabelements are gone from the DOM entirely (not merely hidden), while static siblings outside the collection render fine.Things I verified while debugging:
react-aria-components@1.19.0bundle.dist/private/collections/Document.mjscontains the patchedqueueUpdate(this.collection = this.collection.clone()before notifying subscriptions) andgetCollectionreturningthis.collectionwhileinSubscription. So this is not a stale-dependency problem.useStaterestores all items without remounting:This suggests the collection store repopulates during or after reveal but never schedules the render that would make
useSyncExternalStorere-read it. That is the same class of problem #9300 fixed for the mount path, but on the reappear path.Document.tssince fix: collections nested within Activities (React 19.2) #9300 are unrelated (a Tree refactor and package consolidation), no open issue or PR tracks this case, and no newer stable release exists.💁 Possible Solution
Presumably the reveal path (
reappearLayoutEffects: refs and effects re-attach,useSyncExternalStoreresubscribes) needs the same "clone so React queues a render" treatment that #9300 applied toqueueUpdate, or the store needs to schedule one render on resubscribe when its snapshot changed while hidden.Happy to test a patch; we can reproduce this reliably.
🔦 Context
We hit this in a production dashboard after enabling Next.js 16 Cache Components. Every list and tab bar in the app disappears whenever a user navigates away from a page and back. We are shipping the re-render-on-reveal hook above as a temporary workaround in our shared component wrappers.
🖥️ Steps to Reproduce
Observed in a Next.js 16 app (
cacheComponents: true), where the router drives the Activity boundaries:GridList(orTabs) populated with items. Items render correctly.<Activity mode="hidden">; the DOM is preserved and effects are cleaned up.mode="visible".GridListitems /TabListtabs are gone from the DOM.Equivalent pure-React shape (matches what the Next router does):
Note the difference from #9173's reproduction, which started hidden. The tests added in #9300 cover the starts-hidden case.
Version
react-aria-components 1.19.0 (resolving nested react-aria 3.50.0 / react-stately 3.48.0), React 19.2.7
What browsers are you seeing the problem on?
Chrome
What operating system are you using?
macOS
🧢 Your Company/Team
Terra (tryterra.co)
🕷 Tracking Issue
n/a