Skip to component content
Collection075 / 155

VirtualizedCollection

Keep a long fixed-height collection responsive by rendering visible rows.

Example

Note 1

Note 2

Note 3

Note 4

Note 5

Note 6

Note 7

Note 8

Note 9

Note 10

Note 11

Note 12

Note 13

Note 14

Note 15

Note 16

Source
VirtualizedCollection.tsxtsx
import { useState } from "react";
import { HStack, Padding, Picker, Text, ViewFrame, VirtualizedCollection, VStack } from "@/ohmygui";

const items = Array.from({ length: 1000 }, (_, index) => index + 1);

export default function Example() {
  const [estimateSize, setEstimateSize] = useState("44");
  const [overscan, setOverscan] = useState("5");

  return (
    <VStack gap="sm" align="stretch">
      <HStack gap="md" wrap>
        <Picker label="Estimated row height" value={estimateSize} onChange={(event) => setEstimateSize(event.currentTarget.value)} items={[{ value: "36", label: "36 px" }, { value: "44", label: "44 px" }, { value: "60", label: "60 px" }]} />
        <Picker label="Overscan rows" value={overscan} onChange={(event) => setOverscan(event.currentTarget.value)} items={[{ value: "2", label: "2" }, { value: "5", label: "5" }, { value: "10", label: "10" }]} />
      </HStack>
      <ViewFrame height={240}>
        <VirtualizedCollection
          aria-label="One thousand notes"
          estimateSize={Number(estimateSize)}
          overscan={Number(overscan)}
          items={items}
          getKey={(item) => item}
          render={(item, index) => (
            <Padding padding="sm">
              <HStack justify="between" align="center">
                <Text as="p">Note {item}</Text>
                <Text variant="metadata" color="muted">Row {index + 1}</Text>
              </HStack>
            </Padding>
          )}
        />
      </ViewFrame>
      <Text as="p" variant="metadata" color="muted">1,000 items · keyed by item value</Text>
    </VStack>
  );
}