diff --git a/packages/react-aria-components/stories/GridList.stories.tsx b/packages/react-aria-components/stories/GridList.stories.tsx
index 9710c97e31f..92d62ab384a 100644
--- a/packages/react-aria-components/stories/GridList.stories.tsx
+++ b/packages/react-aria-components/stories/GridList.stories.tsx
@@ -1141,3 +1141,27 @@ GridListWithTextfield.story = {
}
}
};
+
+function VirtualizedDisplayNoneToggleRender() {
+ let [visible, setVisible] = useState(true);
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+export const VirtualizedDisplayNoneToggle: StoryObj = {
+ render: VirtualizedDisplayNoneToggleRender,
+ parameters: {
+ description: {
+ data: 'toggling hide and show should not cause the items to disappear'
+ }
+ }
+};
diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx
index d7b944e1f73..a8f13c11242 100644
--- a/packages/react-aria-components/test/GridList.browser.test.tsx
+++ b/packages/react-aria-components/test/GridList.browser.test.tsx
@@ -11,10 +11,13 @@
*/
import {expect, it} from 'vitest';
+import {GridLayout} from '../src/GridLayout';
import {GridList, GridListItem} from '../src/GridList';
-import React from 'react';
+import React, {useState} from 'react';
import {render} from 'vitest-browser-react';
+import {Size} from 'react-stately/useVirtualizerState';
import {User} from '@react-aria/test-utils';
+import {Virtualizer} from '../src/Virtualizer';
function Grid() {
return (
@@ -36,6 +39,37 @@ function Grid() {
);
}
+function VirtualizedDisplayNone() {
+ let [visible, setVisible] = useState(true);
+ let items = Array.from({length: 100}, (_, i) => ({id: i, name: `Item ${i}`}));
+ return (
+
+
+
+
+
+ {(item: {id: number; name: string}) => (
+ {item.name}
+ )}
+
+
+
+
+ );
+}
+
it.each`
interactionType
${'mouse'}
@@ -64,3 +98,25 @@ it.each`
expect(rows[8].getAttribute('aria-selected')).toBe('true');
expect(document.activeElement).toBe(rows[8]);
});
+
+it('virtualizer renders items after toggling display:none', async () => {
+ let testUtilUser = new User();
+ let {container} = await render();
+
+ let gridlist = container.querySelector('[role=grid]') as HTMLElement;
+ let tester = testUtilUser.createTester('GridList', {
+ root: gridlist,
+ layout: 'grid'
+ });
+
+ await expect(tester.getRows().length).toBeGreaterThan(0);
+ let button = container.querySelector('[data-testid=toggle]') as HTMLElement;
+
+ await button.click();
+ await button.click();
+ await expect(tester.getRows().length).toBeGreaterThan(0);
+
+ await button.click();
+ await button.click();
+ await expect(tester.getRows().length).toBeGreaterThan(0);
+});
diff --git a/packages/react-aria/src/virtualizer/useVirtualizerItem.ts b/packages/react-aria/src/virtualizer/useVirtualizerItem.ts
index a76a6e74431..ad973570b53 100644
--- a/packages/react-aria/src/virtualizer/useVirtualizerItem.ts
+++ b/packages/react-aria/src/virtualizer/useVirtualizerItem.ts
@@ -10,6 +10,7 @@
* governing permissions and limitations under the License.
*/
+import {isElementVisible} from '../utils/isElementVisible';
import {Key, RefObject} from '@react-types/shared';
import {LayoutInfo, Size} from 'react-stately/useVirtualizerState';
import {useCallback} from 'react';
@@ -31,6 +32,12 @@ export function useVirtualizerItem(options: VirtualizerItemOptions): {updateSize
let updateSize = useCallback(() => {
if (key != null && ref.current) {
+ // if the virtualized item is not visible (aka display none on virtualized collection),
+ // we want to avoid reporting size 0 otherwise we get into a state where the virtualizer renders 0 items
+ // when it is hidden and thus won't remeasure when it is is unhidden
+ if (!isElementVisible(ref.current)) {
+ return;
+ }
let size = getSize(ref.current);
virtualizer.updateItemSize(key, size);
}
diff --git a/vitest.browser.config.ts b/vitest.browser.config.ts
index aeede49a7a6..3dfb572a81e 100644
--- a/vitest.browser.config.ts
+++ b/vitest.browser.config.ts
@@ -171,6 +171,10 @@ declare module 'vitest/browser' {
}
export default defineConfig({
+ define: {
+ // run in dev mode so virtualizer and other test-env shortcuts are disabled
+ 'process.env.NODE_ENV': '"development"'
+ },
plugins: [
// @ts-expect-error
macros.vite(), // Must be first!