T
TanStack3y ago
extended-yellow

Switching between finite and infinite scrolling throws dynamic measurements off

Hey I have an app with a list that becomes infinitely scrollable, by pushing a load more button. I.e. rendering a page of about 20 items with the “load more” button at the end of the page. I have an almost working version of this, but sometimes switching from a finite to an infinite list causes the page’s scroll position to jump. Getting the value of window.scrollY is e.g. 18636 before rendering more content and 19406 after rendering more. This only happens when the list container is scrolled out of view leaving about 60% or less of the container in view. I use the useWindowVirtualizer to make the list a part of pages layout. I need to “inject” one or two elements in the list and have currently done that by using a dynamic list and making one or two elements twice the size of the rest. It seems that when I remove these and hard code the estimated size to match the elements exactly the problem goes away. The hard-coding is not feasible since the elements height varies with viewport width. The problem also goes away when removing switching between finite and infinite scrolling. You can see the issue on this staging env https://staging.thingtesting.com/. Scroll to the bottom of the page and click load more. If the “load more” button is just in view all the content should stay in the same place as expected. Then refresh and try scrolling all the way to bottom before hitting the “load more” button. Here the content jumps down. The issue is even more pronounced on mobile. I have tried to recreate the issue here but to no avail https://codesandbox.io/s/goofy-sunset-mpp2mb Any ideas what might be causing this? Any pointers would be greatly appreciated too. Sorry about the wall of text Thanks!
axrez
CodeSandbox
goofy-sunset-mpp2mb - CodeSandbox
goofy-sunset-mpp2mb by axrez using @tanstack/react-virtual, react, react-dom, react-scripts
4 Replies
genetic-orange
genetic-orange3y ago
Hi, first of all you add/remove items please use getItemKey?: (index: number) => Key; also this should be memoized, default key is used the index of array so when we change the order it could break the list.
genetic-orange
genetic-orange3y ago
This jumping is strange, but i can see it on this staging env, we have logic to adjust scroll position when item size changes here https://github.com/TanStack/virtual/blob/beta/packages/virtual-core/src/index.ts#L554-L563 it's used mostly when scrolling up to don't get this jumping effect to compensate difference with estimateSize
GitHub
virtual/index.ts at beta · TanStack/virtual
🤖 Headless UI for Virtualizing Large Element Lists in JS/TS, React, Solid, Vue and Svelte - virtual/index.ts at beta · TanStack/virtual
genetic-orange
genetic-orange3y ago
ooo yeah something is wrong with keys, checkout data-index changes kinda wrong
extended-yellow
extended-yellowOP3y ago
Thanks for getting back to me and catching the data-index stuff. I managed to fix this problem by using the getItemKey like piecyk said. I was adding and removing a loader/load more button on an index that would later be occupied by an item of different size. Giving this loader a specific key instead of just the index fixed the issue.
const getItemKey = useCallback(
(index: number) => {
return index === totalItems ? 'loading' : index
},
[totalItems]
)
const getItemKey = useCallback(
(index: number) => {
return index === totalItems ? 'loading' : index
},
[totalItems]
)

Did you find this page helpful?