Skip to content

fix(react-virtual): grow size container before scroll sync on end-anchored prepend#1237

Merged
piecyk merged 2 commits into
TanStack:mainfrom
piecyk:fix/direct-dom-prepend-scroll-clamp
Jul 20, 2026
Merged

fix(react-virtual): grow size container before scroll sync on end-anchored prepend#1237
piecyk merged 2 commits into
TanStack:mainfrom
piecyk:fix/direct-dom-prepend-scroll-clamp

Conversation

@piecyk

@piecyk piecyk commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes a whitespace gap at the top of the list after an end-anchored prepend (e.g. "load older messages" in a chat pinned to the bottom) when using directDomUpdates mode.

Root cause

On a prepend, setOptions grows the total size and bumps scrollOffset to the new bottom in the same render pass. The scroll position is then synced in the _willUpdate layout effect — but the size container's height is written by the separate applyDirectStyles layout effect that runs after it. So _willUpdate writes scrollTop to the new bottom while the container is still at its old, shorter height, and the browser clamps the write to the stale scrollHeight. The list is left with a gap at the top until the next scroll re-reconciles.

It only bites when at-end (that's the only time the new scroll target exceeds the stale scrollHeight), and only in directDomUpdates mode — React-rendered sizers receive their height during render, so they're already tall by the layout-effect phase.

Fix

Grow the size container to the new total before _willUpdate syncs the scroll position. Item positions are still written afterwards by applyDirectStyles. The size write is extracted into a small applyContainerSize helper (idempotent, guarded by lastSize) reused by both call sites.

Testing

  • @tanstack/react-virtual: 7/7 pass; tsc --noEmit clean.
  • Verified manually in the React chat example: scroll to bottom → "Load older" no longer leaves a gap; the list stays pinned to the bottom.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed a scrolling issue when items are prepended to the end-anchored list.
    • Prevented temporary whitespace caused by scroll position being clamped to an outdated list size.
    • Improved direct DOM updates so container dimensions are refreshed before scroll synchronization.

piecyk and others added 2 commits July 20, 2026 13:19
…hored prepend

In directDomUpdates mode the size container's height was written by the
applyDirectStyles layout effect, which runs *after* the _willUpdate effect
syncs the scroll position. On an end-anchored prepend, _willUpdate writes
scrollTop to the new bottom while the container is still at its old, shorter
height, so the browser clamps the write to the stale scrollHeight and the list
is left with a gap at the top until the next scroll.

Grow the container to the new total size before _willUpdate runs. React-rendered
sizers are unaffected — they receive their height during render.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nx-cloud

nx-cloud Bot commented Jul 20, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit b8c2cb3

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 39s View ↗
nx run-many --target=build --exclude=examples/** ✅ Succeeded 20s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-20 11:22:24 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 20, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-virtual

npm i https://pkg.pr.new/@tanstack/angular-virtual@1237

@tanstack/lit-virtual

npm i https://pkg.pr.new/@tanstack/lit-virtual@1237

@tanstack/marko-virtual

npm i https://pkg.pr.new/@tanstack/marko-virtual@1237

@tanstack/react-virtual

npm i https://pkg.pr.new/@tanstack/react-virtual@1237

@tanstack/solid-virtual

npm i https://pkg.pr.new/@tanstack/solid-virtual@1237

@tanstack/svelte-virtual

npm i https://pkg.pr.new/@tanstack/svelte-virtual@1237

@tanstack/virtual-core

npm i https://pkg.pr.new/@tanstack/virtual-core@1237

@tanstack/vue-virtual

npm i https://pkg.pr.new/@tanstack/vue-virtual@1237

commit: b8c2cb3

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The direct DOM update path now applies the virtualization container’s total size separately and before item positioning or _willUpdate scroll synchronization, preventing stale scroll extents during end-anchored prepends. A patch changeset documents the fix.

Changes

Direct DOM scroll synchronization

Layer / File(s) Summary
Container sizing and item positioning
packages/react-virtual/src/index.tsx
Adds an idempotent applyContainerSize helper and invokes it before writing direct item positions.
Pre-scroll synchronization sizing
packages/react-virtual/src/index.tsx, .changeset/fix-direct-dom-prepend-scroll-clamp.md
Applies the container size before _willUpdate synchronizes scroll position and documents the patch release.参考

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: tannerlinsley

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main change: fixing scroll sync by growing the size container first for end-anchored prepends.
Description check ✅ Passed The description covers the summary, root cause, fix, and testing, but omits the template's checklist and release-impact sections.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@piecyk
piecyk merged commit aa536e7 into TanStack:main Jul 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant