javascriptvue.jsvue-componentinfinite-scrollvueuse

VueUse useInfiniteScroll not loading more items


I want to load more artworks if the user scrolls down. Like an infinite scroller. I use VueUse to achieve that and want to use .slice() on my vuex computed store to increment 3 more works each time if I come closer to the bottom of the Dom Element.

The first 3 works load and everything seams fine, but if I scroll down nothing more loads. The sliceNumber didn't increment and no errors appear. Seams like the useInfiniteScroll() function don't trigger any event. 🤔

Did someone see the issue? 😅 Thanks for any help in advance 👍

Here my Vue Component

<template>
<div class="Section Explore">

    <ExploreBanner />

    <div
        ref="workDom"
        class="WorkList flex_c_h flex_wrap gap2">
        <Suspense>

            <WorkThumbnail
                v-for="(work, index) in works"
                :key="work"
                :work="work"
                :index="index" />

            <template #fallback>
                <div>
                    Loading...
                </div>
            </template>

        </Suspense>

    </div>

</div>
</template>

<script>
import {
    ref
} from 'vue'
import WorkThumbnail from '@/components/Explore/WorkThumbnail.vue'
import ExploreBanner from '@/components/Explore/ExploreBanner.vue'
import {
    useInfiniteScroll
} from '@vueuse/core'

export default {
    name: 'Explore',
    setup() {

        const workDom = ref(null)
        const sliceNumber = ref(3)
        console.log(sliceNumber.value)

        useInfiniteScroll(
            workDom,
            () => {
                sliceNumber.value += 3
                console.log(sliceNumber.value)
            }, {
                distance: 10
            }
        )

        return {
            workDom,
            sliceNumber
        }
    },
    components: {
        WorkThumbnail,
        ExploreBanner,

    },
    computed: {
        works() {
            return this.$store.state.works.slice(0, this.sliceNumber)
        }
    },
    mounted() {
        document.documentElement.style.setProperty('--color_p', '#a25aff');
        document.documentElement.style.setProperty('--color_bg', '57, 35, 66');
    },

}
</script>

Solution

  • I tried useInfiniteScroll composable with Vue 3 and it seems working as expected.

    Stackblitz demo here (working only in chrome browser due to cors issue)

    <script setup>
    import { computed, ref } from 'vue'
    import { useInfiniteScroll } from '@vueuse/core'
    import ShowImage from '@/components/ShowImage.vue'
    import { loadMore } from './urls'
    
    const el = ref(null)
    
    const count = computed(() => thumbnails.value.length)
    const thumbnails = ref([])
    
    loadData()
    
    useInfiniteScroll(el, loadData, { distance: 10 })
    
    async function loadData() {
      const moreData = await loadMore(3, count.value)
    
      thumbnails.value = thumbnails.value.concat(moreData)
    }
    </script>
    
    <template>
      <div ref="el" class="my-container">
        <ShowImage v-for="url in thumbnails" :url="url"></ShowImage>
      </div>
      count: {{ count }}
    </template>
    
    <style scoped>
    .my-container {
      border: 1px solid gray;
      overflow-y: scroll;
      margin-top: 10px;
      padding: 10px;
      height: 700px;
    }
    </style>
    

    Note that container is made scrollable with height 700px and initial 3 images overflow vertically so that you can scroll down.

    When distance between container bottom and last image's bottom became smaller than given 10, the composable successfully runs loadData callback to get more urls that will be appended, etc.