Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/@react-spectrum/list/stories/ListView.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -517,3 +517,33 @@ function Demo(props) {
</ListView>
);
}

const manyItems = [];
for (let i = 0; i < 500; i++) {manyItems.push({key: i, name: `item ${i}`});}

function DisplayNoneComponent(args) {
const [isDisplay, setIsDisplay] = useState(false);
useEffect(() => {
const timeout = setTimeout(() => setIsDisplay(true), 10000);
return () => clearTimeout(timeout);
}, []);

return (
<div style={!isDisplay ? {display: 'none'} : null}>
<ListView aria-label="Many items" items={manyItems} width="300px" height="200px" {...args}>
{(item: any) => (
<Item key={item.key} textValue={item.name}>
<Text>
{item.name}
</Text>
</Item>
)}
</ListView>
</div>
);
}

export const DisplayNone: ListViewStory = {
render: (args) => <DisplayNoneComponent {...args} />,
name: 'display: none with many items'
};
2 changes: 1 addition & 1 deletion packages/@react-stately/layout/src/ListLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
let layoutNode = this.buildChild(node, 0, y);
y = layoutNode.layoutInfo.rect.maxY;
nodes.push(layoutNode);

if (node.type === 'item' && y > this.validRect.maxY) {
y += (this.collection.size - (nodes.length + skipped)) * rowHeight;
break;
Expand Down Expand Up @@ -432,6 +431,7 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
}

updateItemSize(key: Key, size: Size) {
if (size.height === 0) {return false;}
Copy link
Copy Markdown
Contributor Author

@richardbann richardbann May 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear if it is a safe change. Probably the height of a list item is 0 only if display:none set.
On the other hand if somehow the item size is small enough (say 1), react will throw the same exception even if the ListView is visible. This is because after render the size is calculated (1 in this case) and a re-render will add one more item to the visible item's list, which will notice it's size and render again... If the collection is large enough react will treat it as an infinite recursion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The page does not crash if padding is set to 1 on ListLayout, but this is not configurable. Can be verified by setting the padding in ListView.tsx.

let layoutInfo = this.layoutInfos.get(key);
// If no layoutInfo, item has been deleted/removed.
if (!layoutInfo) {
Expand Down