Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected scroll jump with initialIndex set to last item #73

Open
DmitryLudin opened this issue Oct 17, 2023 · 8 comments
Open

Unexpected scroll jump with initialIndex set to last item #73

DmitryLudin opened this issue Oct 17, 2023 · 8 comments

Comments

@DmitryLudin
Copy link

DmitryLudin commented Oct 17, 2023

Hello! First of all, I would like to express my gratitude for your library - it's the best virtualization tool I've ever worked with. However, I came across a visual issue: when the initialIndex is set as the last item in the list, there's a noticeable jump in scrolling. This is particularly noticeable when using initialDelay. At the moment, we've addressed this with the visibility: hidden hack for the container until all elements are fully rendered. Do you perhaps have a more optimal solution?

          <ViewportList
            viewportRef={scrollAreaRef}
            items={data}
            overscan={20}
            initialIndex={data.length - 1}
            initialPrerender={10}
            initialDelay={1000}
            initialAlignToTop={false}
            indexesShift={indexesShift}
            onViewportIndexesChange={handleViewportIndexesChange}
          >
            {handleRenderItem}
          </ViewportList>

first video without the visibility: hidden hack
second with the visibility: hidden hack

Screen.Recording.2023-10-17.at.10.34.28.mov
Screen.Recording.2023-10-17.at.10.51.52.mov
@oleggrishechkin
Copy link
Owner

Hi, @DmitryLudin

initialDelay is an exactly delay for scroll to items on initial render. This prop was created because ios safari works unusual with scrolling and scroll may be not be performed in this browser without short delay. And delay will be applied to mobile safari only by default. I can suggest you to not use this prop at all. If you have loadable items and you want to scroll to the last item when all items will be loaded, you need to manually call scrollToIndex method. Initial index will work only if you have items on initial render.

If omitting delay not work for you, could you give a short reproduction? (CodeSandBox, repository). I'll check it closer.

@DmitryLudin
Copy link
Author

In this case, using initialDelay, I wanted to demonstrate a visual bug when the data from the server is already there and just a list is being rendered. Without initialDelay, this visual bug is also noticeable but not as much. For a fraction of a second, list items appear (it seems these are the first items in the list), then they disappear, and then the last ones are displayed again.

Here's a small demonstration of how to reproduce it. You can click on the Reset button (so you don't have to reload the page) and you'll see that the list flashes. I have a theory that we iterate over an array of identifiers, and in the list component itself, we retrieve data from the state manager by this identifier, which may cause the flickering.

https://codesandbox.io/s/eager-ben-5zyjld?file=/src/ui/post-list.tsx

@DmitryLudin
Copy link
Author

If you uncomment the line with // visibility: isItemsMounted ? "visible" : "hidden"
you can notice that there is no flickering of the list during the initial load. Everything else works perfectly and no other issues were noticed, thank you :)

@oleggrishechkin
Copy link
Owner

oleggrishechkin commented Oct 17, 2023

Hi, @DmitryLudin thank you for detailed reproduction! I think it can be an issue with itemSize and itemMargin. If you are not set these props, ViewportList will need to calculate them automatically on mount and only on the next frame scroll will be happened. I think you can provide itemSize={100} (something close to an average size of item) and itemMargin={0} (if you are not using margins).

@DmitryLudin
Copy link
Author

DmitryLudin commented Oct 19, 2023

Hello! Thanks for the response. Indeed, if you specify the size of the item, the jumps disappear. Unfortunately, this works well only in this demo. In our application, the sizes of the items can vary significantly, so it's more difficult to choose an optimal size there. But thanks again!
I also noticed a small problem both in our application and in the demo: on a mobile device, the scroll gets stuck when scrolling up. I haven't looked into it deeply yet, maybe I'm doing something wrong, but I wanted to highlight it. If you're interested in testing, you can open this demo version on a mobile device (I use an iPhone 12 for tests). It only reproduces on the device; in the browser emulator, everything is smooth.
https://5zyjld.csb.app/

P.S. Thanks again for the cool library and best of luck!

@oleggrishechkin
Copy link
Owner

oleggrishechkin commented Oct 19, 2023

@DmitryLudin itemSize prop is some estimated size. Automatically (if prop is not provided), I take all rendered item sizes and compute average size of these items (heights sum / items count)

You can specify minimal size of the item, for example, if you don't know the average size. It should work, in early version of this library I used exactly minItemSize

@oleggrishechkin
Copy link
Owner

oleggrishechkin commented Oct 19, 2023

@DmitryLudin what do you mean scroll stuck? On ios I'm using another type of scroll compensation to prevent scroll jumps on scroll up - negative/positive margin-top. Then you reach a list top I need to reset margin and perform scroll to compensate margin removing, but in ios just scrollBy/set scrollTop/anything don't work - I need to change overflow to hidden, scroll, and return overflow to prev value (auto, for example). This is why momentum scroll stuck at the top of a list when you scroll up in ios. But I think this is better than scroll "jump".

The compensation needed because when new item appears at the top of a list the real item size can be different than virtualized one and I need to scroll by item size difference.

So the answer to "why scroll stucks at the top" is "this is a limitation for ios safari"

@DmitryLudin
Copy link
Author

Understood, thank you very much for the answer! Safari has indeed thrown some challenges our way for our application. Regarding the stuck scroll, I can attach a video. I'm not sure if the user experience of scrolling will be clear from it, but in the video, I try to scroll the page up, and the scroll lags several times in a row. I noticed that this happens only with pagination. As soon as all the data is ready, the scroll works perfectly. So, I'll repeat, it seems I might just be doing something wrong and will delve deeper into the problem in my code. I won't distract and detain you any further!

scroll-stuck.mp4

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

No branches or pull requests

2 participants