petyosi / react-virtuoso

The most powerful virtual list component for React
https://virtuoso.dev
MIT License
5.25k stars 301 forks source link

[BUG] scrollSeekConfiguration with reversed list: flickering #410

Open eliasws opened 3 years ago

eliasws commented 3 years ago

Describe the bug When using scrollSeekConfiguration with a reversed list the scrollSeekConfiguration.onEnter callback is called directly on the first render with a high velocity (probably height of the list) which causes the ScrollSeekPlaceholder to be shown. It seems that this was introduced in version 0.21.0-alpha.1.

Reproduction https://codesandbox.io/s/react-virtuoso-scrolling-issue-forked-xis50?file=/src/App.js

To Reproduce

  1. Reload the page
  2. Check console, scrollSeekConfiguration.onEnter gets called with a velocity of 1446
  3. Items render -> then the ScrollSeekPlaceholder gets rendered for split second -> Items render

Expected behaviour scrollSeekConfiguration.onEnter should not be called on first render without actual scrolling

Screenshots

Desktop (please complete the following information):

Additional context isScrolling gets also called on first render.

petyosi commented 3 years ago

Confirming that this is a bug, The scrollSeek system should wait for the didMount observable.

eliasws commented 3 years ago

I tried to implement it and create a PR. At least in this case didMount seems to be always true (so would not have any effect):

pipe(
    scrollVelocity,
    withLatestFrom(scrollSeekConfiguration, isSeeking, rangeChanged, didMount),
    filter(([_, config]) => !!config),
    map(([speed, config, isSeeking, range, didMount]) => {
      const { exit, enter } = config as ScrollSeekConfiguration
      console.log("DID MOUNT", didMount);
      if (isSeeking) {
        if (exit(speed, range)) {
          return false
        }
 // ........
petyosi commented 3 years ago

True. It might have to wait for this flag: https://github.com/petyosi/react-virtuoso/blob/master/src/initialTopMostItemIndexSystem.ts#L10

eliasws commented 3 years ago

scrolledToInitialItem has the same problem :) (always true).

Seems like https://github.com/petyosi/react-virtuoso/blob/392b9c8e717f9a937573c3db0a17d50d0d4a3132/src/initialTopMostItemIndexSystem.ts#L34 is firing to fast.

For now i just disabled the scrollSeek.

petyosi commented 3 years ago

This flag will turn true after the initial destination has been reached. My understanding is that you are trying to avoid that call.

At any case, I will look at that at some point.

eliasws commented 3 years ago

@petyosi FYI, just checked: Same happens with endless scroll ("prepending-items"); the velocity "jumps" for a moment when startReached is called and the new items are prepended.

petyosi commented 3 years ago

That's understandable, based on how velocity and prepending work. Scrolling is readjusted to accommodate the prepended items.

phenry20 commented 3 years ago

Any updates?

tomholford commented 1 year ago

Tried to use scrollSeek + reverse endless and got the same results. Ended up disabling it.

In the meantime, is there a callback that can be hooked into to get the current scroll velocity? The goal is to adjust the fetch page size - if the user is scrolling quickly, we will fetch more data to pre-pend to the list

petyosi commented 1 year ago

@tomholford you can hook up to the scrollerRef, listen to scrollTop changes and calculate the velocity.

tomholford commented 1 year ago

@tomholford you can hook up to the scrollerRef, listen to scrollTop changes and calculate the velocity.

Great suggestion, will give this a shot. Thanks!