Batch virtual item visibility updates

This commit is contained in:
Shantur Rathore
2025-12-02 11:45:12 +00:00
parent 73b59d8266
commit c614da3e3c

View File

@@ -103,6 +103,29 @@ export default function VirtualItem(props: VirtualItemProps) {
const resolved = resolveChildren(() => props.children)
const [isIntersecting, setIsIntersecting] = createSignal(true)
const [measuredHeight, setMeasuredHeight] = createSignal(sizeCache.get(props.cacheKey) ?? 0)
let pendingVisibility: boolean | null = null
let visibilityFrame: number | null = null
const flushVisibility = () => {
if (visibilityFrame !== null) {
cancelAnimationFrame(visibilityFrame)
visibilityFrame = null
}
if (pendingVisibility !== null) {
setIsIntersecting(pendingVisibility)
pendingVisibility = null
}
}
const queueVisibility = (nextValue: boolean) => {
pendingVisibility = nextValue
if (visibilityFrame !== null) return
visibilityFrame = requestAnimationFrame(() => {
visibilityFrame = null
if (pendingVisibility !== null) {
setIsIntersecting(pendingVisibility)
pendingVisibility = null
}
})
}
const [hasMeasured, setHasMeasured] = createSignal(sizeCache.has(props.cacheKey))
const virtualizationEnabled = () => (props.virtualizationEnabled ? props.virtualizationEnabled() : true)
@@ -167,7 +190,7 @@ export default function VirtualItem(props: VirtualItemProps) {
}
const margin = props.threshold ?? DEFAULT_MARGIN_PX
intersectionCleanup = subscribeToSharedObserver(wrapperRef, targetRoot, margin, (entry) => {
setIsIntersecting(entry.isIntersecting)
queueVisibility(entry.isIntersecting)
})
}
@@ -223,6 +246,7 @@ export default function VirtualItem(props: VirtualItemProps) {
onCleanup(() => {
cleanupResizeObserver()
cleanupIntersectionObserver()
flushVisibility()
})
const wrapperClass = () => ["virtual-item-wrapper", props.class].filter(Boolean).join(" ")