petyosi / react-virtuoso

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

[BUG] Issue with prepending items when there is only one group of items using GroupedVirtuoso #886

Closed danielsantiago closed 1 year ago

danielsantiago commented 1 year ago

Describe the bug In case there is only one group of items, when scrolling up to the first item in the list, Virtuoso throws an error in the console and automatically scrolls to the top of the list causing it to call "startReached" infinitely

References:

Reproduction https://codesandbox.io/s/sandpack-project-forked-679enb?file=/App.js

To Reproduce Steps to reproduce the behavior:

  1. Go to the codesanbox link
  2. Scroll up to the first item
  3. See the error in the console: "Warning: 'NaN' is an invalid value for the 'marginTop' css style property."
  4. See infinite prepending loop

Expected behavior It should only load the 50 new items in the existing group and not scroll to the top of the list.

Desktop (please complete the following information):

EdVilu commented 1 year ago

I have the same issue. Windows OS, Chrome browser. If initially there's only one group, when prepending more items or more groups, this error shows up and described scroll behavior happens. Logger shows that "received item sizes" happens receiving an object with multiple items, one of them having endIndex as NaN and some others then have incorrect height values. Appending a group with 0 count, when there's a single initial group, seems to work around the issue, which suggests that there is a bug with a single group in grouped mode.

Myckam commented 1 year ago

I'm not sure if this is the correct behavior, but patching the library solved the problem for me.

diff --git a/dist/index.mjs b/dist/index.mjs
index 15ee87155278f084857e017b0c7ea23e64e84f6d..3dda9eb47412e55963f7c159f77f39e2263d37d9 100644
--- a/dist/index.mjs
+++ b/dist/index.mjs
@@ -1910,6 +1910,15 @@ const followOutputSystem = system(
   tup(sizeSystem, stateFlagsSystem, scrollToIndexSystem, initialTopMostItemIndexSystem, propsReadySystem, loggerSystem, domIOSystem)
 );
 function groupCountsToIndicesAndCount(counts) {
+  if(counts.length === 1){
+    const items = counts[0];
+
+    return {
+      totalCount: items + 2,
+      groupIndices: [0, items]
+    }
+  }
+
   return counts.reduce(
     (acc, groupCount) => {
       acc.groupIndices.push(acc.totalCount);

The problem itself arises when trying to get the number of items by accessing the next group, and there is only one.

while (recognizedOffsetItems < offset) {
 recognizedOffsetItems++;
 amount += defaultGroupSize;
 let groupItemCount = groupIndices[groupIndex + 1] - groupIndices[groupIndex] - 1; // <-- this place
 if (recognizedOffsetItems + groupItemCount > offset) {
    amount -= defaultGroupSize;
    groupItemCount = offset - recognizedOffsetItems + 1;
  }
 recognizedOffsetItems += groupItemCount;
 amount += getItemOffset(groupItemCount);
 groupIndex++;
}
petyosi commented 1 year ago

Thanks everyone, I am fairly certain that this is a bug I've made, will look into it shortly.

github-actions[bot] commented 1 year ago

:tada: This issue has been resolved in version 4.3.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket: