import React, { useEffect, useRef, useState } from "react"; import ReactDOM from "react-dom/client"; import { useVirtualOverflowY, virtualOverflowCalcVisibleRect } from ".."; import { virtualOverflowUtils } from "../utils"; import { VirtualListY } from "../fixed-list-y"; import { VirtualGrid } from "../fixed-grid"; const itemsLine = Array.from({ length: 300 }).map((_, i) => `item ${i}`); const itemsGrid = Array.from({ length: 300 }).map((_, iy) => Array.from({ length: 300 }).map((_, ix) => `item ${ix} ${iy}`)); function ListWithHookExample() { const [items, setItems] = useState([] as string[]); const containerRef = useRef(undefined!); const infoRef = useRef(undefined!); const itemHeight = 40; const { renderedItems, updateViewRect, itemSlice } = useVirtualOverflowY({ containerRef, itemHeight, itemsLengthY: items.length, overscanItemsCount: 3, calcVisibleRect: virtualOverflowUtils.calcVisibleRectOverflowed, renderItem: (itemIndex, offsetTop, item = items[itemIndex]) => (
{item}
), }); useEffect(() => { // in case of animated containers // setInterval(() => updateViewRect(), 8); setInterval(() => { const visibleRect = virtualOverflowCalcVisibleRect(containerRef.current); infoRef.current.innerText = `Visible rect of content:\n\n${JSON.stringify(visibleRect, null, 2)}`; }, 24); }, []); useEffect(() => { if (itemSlice.topStartIndex + itemSlice.lengthY >= items.length - 4) { // load more setItems(prev => [...prev, ...itemsLine]); } }, [itemSlice.topStartIndex, itemSlice.lengthY]); return ( <>
{renderedItems}
); } function VerticalListExample() { const items = itemsLine; return (
x} renderItem={item =>
{item}
} />
); } function GridExample() { const items = itemsGrid; return (
x} overscanItemsCount={3} renderItem={item =>
{item}
} />
); } function App() { return (
Scroll me down
Scroll me down
); } const rootElement = document.getElementById("demo")!; const root = ReactDOM.createRoot(rootElement); root.render( );