diff --git a/examples/grid-infinite-data.tsx b/examples/grid-infinite-data.tsx
new file mode 100644
index 000000000..b93120dd5
--- /dev/null
+++ b/examples/grid-infinite-data.tsx
@@ -0,0 +1,32 @@
+import * as React from 'react'
+import { useState } from 'react'
+import { VirtuosoGrid } from '../src'
+
+function generateItems(length: number) {
+ return Array.from({ length }, (_, index) => `My Item ${index}`)
+}
+
+const itemContent = (_: number, data: string) => {
+ return
{data}
+}
+export function Example() {
+ const [data, setData] = useState(() => generateItems(5))
+
+ const loadMore = () => {
+ setTimeout(() => {
+ setData((prevData) => {
+ return generateItems(prevData.length + 5)
+ })
+ }, 100)
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/src/gridSystem.ts b/src/gridSystem.ts
index c3e47a6e5..917d83901 100644
--- a/src/gridSystem.ts
+++ b/src/gridSystem.ts
@@ -310,11 +310,25 @@ export const gridSystem = /*#__PURE__*/ u.system(
const endReached = u.streamFromEmitter(
u.pipe(
- u.duc(gridState),
- u.filter(({ items }) => items.length > 0),
- u.withLatestFrom(totalCount, hasScrolled),
- u.filter(([{ items }, totalCount, hasScrolled]) => hasScrolled && items[items.length - 1].index === totalCount - 1),
- u.map(([, totalCount]) => totalCount - 1),
+ u.combineLatest(gridState, totalCount),
+ u.filter(([{ items }]) => items.length > 0),
+ u.withLatestFrom(hasScrolled),
+ u.filter(([[gridState, totalCount], hasScrolled]) => {
+ const lastIndex = gridState.items[gridState.items.length - 1].index
+ const isLastItemRendered = lastIndex === totalCount - 1
+
+ // User has scrolled
+ if (hasScrolled) return isLastItemRendered
+
+ // User has not scrolled, so check whether grid is fully rendered
+ const isFullyRendered =
+ gridState.bottom > 0 && gridState.itemHeight > 0 && gridState.offsetBottom === 0 && gridState.items.length === totalCount
+
+ return isFullyRendered && isLastItemRendered
+ }),
+ u.map(([[, totalCount]]) => {
+ return totalCount - 1
+ }),
u.distinctUntilChanged()
)
)