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

fix(VInfiniteScroll): keep triggering loading logic until isInterseting becomes false #17475

Merged
merged 11 commits into from
Jun 27, 2023

Conversation

yuwu9145
Copy link
Member

@yuwu9145 yuwu9145 commented May 27, 2023

fixes #17358

Description

Markup:

<template>
  <v-app>
    <v-main>
      <v-list>
        <v-infinite-scroll mode="intersect" @load="load">
          <v-list-item v-for="(item, index) in items" :key="item">
            <v-list-item-title>
              Item #{{ item }}
            </v-list-item-title>
          </v-list-item>
          <template v-slot:empty>
            <v-alert type="warning">No more items!</v-alert>
          </template>
          <template v-slot:error="{ props }">
            <v-alert type="error">
              <div class="d-flex justify-space-between align-center">
                Something went wrong...
                <v-btn
                  color="white"
                  variant="outlined"
                  size="small"
                  v-bind="props"
                >
                  Retry
                </v-btn>
              </div>
            </v-alert>
          </template>
        </v-infinite-scroll>
      </v-list>
    </v-main>
  </v-app>
</template>

<script setup>
import { ref } from 'vue'

const items = ref(Array.from({ length: 3 }, (k, v) => v + 1))

let count = 0
const load = async ({ done }) => {
  setTimeout(() => {
    count++
    if (count < 2) { // adjust number to control loading cycles
      items.value.push(...Array.from({ length: 3 }, (k, v) => v + items.value.at(-1) + 1))
      done('ok')
    } else {
      done('empty')
      // done('error')
    }

  }, 1000)
}
</script>

@yuwu9145 yuwu9145 marked this pull request as ready for review May 30, 2023 12:57
@yuwu9145 yuwu9145 requested review from nekosaur and KaelWD May 30, 2023 12:58
@johnleider johnleider added T: bug Functionality that does not work as intended/expected C: VVirtualScroll labels May 30, 2023
@johnleider johnleider added this to the v3.3.x milestone May 30, 2023
@johnleider
Copy link
Member

I don't quite understand this bug. Is the intent for the loading animation to show always?

@yuwu9145
Copy link
Member Author

I don't quite understand this bug. Is the intent for the loading animation to show always?

It should keep triggering load emit until VInfiniteScrollIntersect disappears

@johnleider
Copy link
Member

I'm not completely on board with this even being a bug. If I have an infinite scroller that doesn't have enough items to fill the viewport, I wouldn't want it to constantly run load with the circular progress visible.

If we were to do this, I would expect it to say "No more items" or something similar after a duration of time where nothing is being loaded.

@yuwu9145
Copy link
Member Author

yuwu9145 commented Jun 2, 2023

I'm not completely on board with this even being a bug. If I have an infinite scroller that doesn't have enough items to fill the viewport, I wouldn't want it to constantly run load with the circular progress visible.

If we were to do this, I would expect it to say "No more items" or something similar after a duration of time where nothing is being loaded.

The issue occurs when a user has a large number of total items but is using pagination, for example, loading 3 items per load.

  • On small/short screens, it works fine as the user can scroll to the bottom to trigger the next load.
  • On big/high screens, it only triggers the load once to load a total of 6 items, even though there is still plenty of space and more items to be loaded.

@AntoineRobert
Copy link

I'm not completely on board with this even being a bug. If I have an infinite scroller that doesn't have enough items to fill the viewport, I wouldn't want it to constantly run load with the circular progress visible.

If we were to do this, I would expect it to say "No more items" or something similar after a duration of time where nothing is being loaded.

There are more items, they are just not being loaded.

Maybe this illustrates the issue better:

two list

cards

If i have small item with big screens i am gonna have to load 200+ items minimum per call to make sure the infinite scroller doesn't get stuck.

@johnleider
Copy link
Member

I would still want a way to fast fail out of the loader perpetually being there.

@eldjh3
Copy link

eldjh3 commented Jun 12, 2023

I've been hit by this issue too. I agree that the load event should be triggered continually until either of the following occur:

  1. The load function returns a status of empty indicating no more content to load. In this case load is never re-triggered
  2. Enough content is loaded such that the intersection div moves outside the enclosing scrollable area. In this case load is re-triggered when the intersection re-enters the enclosing area (root element).

Forcing developers to load enough content to fill the scrollable area to prevent the issue is not really workable.

I'm no UX expert but I think this is actually a better user experience too. If the content area is large enough to show it and there is more data available, it makes sense to continue to load it. Loading in smaller chunks allows users to act on 'earlier' loaded items if desired but still see that more data is coming. The smaller chunk size can also help to lower demands on the back end and bandwidth.

Incidentally, I've also just opened #17583 that currently allows a workaround for this issue. Don't specify the margin explicitly, resize the viewport and the infinite scroll can be triggered to load more content avoiding this issue. But if that issue is fixed before this, the workaround stops working.

@eldjh3
Copy link

eldjh3 commented Jun 12, 2023

I would still want a way to fast fail out of the loader perpetually being there.

For this, I think it's really just the case where badly behaved developers return a status of ok when they should return empty. Otherwise the component would only be in loading state until enough data was loaded to move the intersection out of the parent wrapper, however many loading cycles that takes.

To cover this case you could potentially have some functionality to determine whether the number of child elements has changed each cycle and if multiple cycles occur with no change then abort the load loop. But that seems like extra complexity to cope with incorrect use of the API.

@johnleider
Copy link
Member

I would still want a way to fast fail out of the loader perpetually being there.

For this, I think it's really just the case where badly behaved developers return a status of ok when they should return empty. Otherwise the component would only be in loading state until enough data was loaded to move the intersection out of the parent wrapper, however many loading cycles that takes.

To cover this case you could potentially have some functionality to determine whether the number of child elements has changed each cycle and if multiple cycles occur with no change then abort the load loop. But that seems like extra complexity to cope with incorrect use of the API.

This is a good point. @yuwu9145 can we add an example under the guide explaining this?

@yuwu9145
Copy link
Member Author

yuwu9145 commented Jun 19, 2023

I don't think it's our responsibility of coping with incorrect use of the API from user's land (return a status of ok when they should return empty)

However, when user does use API correctly to properly return empty or error status. It shall display fast fail state (display empty/error slots) as opposed to the loader perpetually being there.

Playground has been updated to include empty/error examples

@johnleider johnleider enabled auto-merge (squash) June 27, 2023 18:16
@johnleider johnleider disabled auto-merge June 27, 2023 18:41
@johnleider johnleider merged commit f898404 into master Jun 27, 2023
@johnleider johnleider deleted the fix-17358 branch June 27, 2023 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VInfiniteScroll T: bug Functionality that does not work as intended/expected
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug Report][3.2.3] VInfiniteScroll get stuck if the VInfiniteScrollIntersect stays in view
5 participants