Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions .changeset/cold-ads-lose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/virtual-core': patch
---

Fixed observeElementOffset to prevent continuous rerenders during or after scrolling
15 changes: 15 additions & 0 deletions packages/virtual-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,21 @@ export class Virtualizer<

this.unsubs.push(
this.options.observeElementOffset(this, (offset, isScrolling) => {
// A scroll event that reports movement but lands on the offset we
// already hold β€” and isn't a self-write read-back β€” is a spurious
// no-op re-emit that Safari/Firefox fire after a re-render's layout
// (Chrome doesn't). Treating it as scrolling re-arms `isScrolling`,
// which forces a render that triggers another such event: an
// infinite re-render loop. Ignore it. (Self-writes are handled by
// the `_intendedScrollOffset` reconciliation just below.)
if (
isScrolling &&
this._intendedScrollOffset === null &&
offset === this.scrollOffset
) {
return
}

// If this scroll event looks like the browser's read-back of a
Comment thread
dracofulmen marked this conversation as resolved.
// value we just wrote, prefer our intended (sub-pixel-accurate)
// value over the browser's rounded one. The 1.5 px tolerance is
Expand Down