TanStack / virtual

🤖 Headless UI for Virtualizing Large Element Lists in JS/TS, React, Solid, Vue and Svelte

Home Page:https://tanstack.com/virtual

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scroll offset with dynamic sizes not working properly in React 16

hdwatts opened this issue · comments

Describe the bug

When adjusting scales of items, the scroll offset is maintained when items get bigger, but are lost in a React 16 environment when items get smaller.

Your minimal, reproducible example

https://codesandbox.io/p/devbox/funny-sound-9dvq49?file=%2Fsrc%2Fmain.tsx%3A92%2C34

Steps to reproduce

  1. Scroll down
  2. Zoom in (Scroll position is maintained, sometimes)
  3. Zoom out (Scroll position is shifted down a third of the page, everytime)

Expected behavior

As a user, my scroll position should remain the same as my items scale, as it is in React 18

React 18 example: https://codesandbox.io/p/devbox/suspicious-orla-wcmzp8?file=%2Fsrc%2Fmain.tsx%3A96%2C37

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • OS: Mac - Browser: Chrome - Version: 120.0.6099.216

tanstack-virtual version

v3.0.1

TypeScript version

4.9.5 and 5.2.2

Additional context

No response

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

This modification to resizeItem appears to solve for me.

resizeItem = (item: VirtualItem, size: number) => {
    const itemSize = this.itemSizeCache.get(item.key) ?? item.size
    const delta = size - itemSize

    if (delta !== 0) {
      //
      // note change below
      //
      if (
        item.start < this.scrollOffset + this.scrollAdjustments
      ) {
        if (process.env.NODE_ENV !== 'production' && this.options.debug) {
          console.info('correction', delta)
        }

        this._scrollToOffset(this.scrollOffset, {
          adjustments: (this.scrollAdjustments += delta),
          behavior: undefined,
        })
      }

      this.pendingMeasuredCacheIndexes.push(item.index)
      this.itemSizeCache = new Map(this.itemSizeCache.set(item.key, size))

      this.notify(false)
    }
  }