javascriptvue.jsinfinite-scrollvue-composition-apivueuse

How can i use vue-virtual-scroller with vue use useInfiniteScroll?


I'm currently working on implementing infinite scroll in a Vue application using the useInfiniteScroll function from @vueuse/core. However, I'm facing an issue with binding the ref to the scrollable element.

The infinite scroll functionality is not working as expected. The useInfiniteScroll callback function is not triggered when scrolling near the bottom of the element. I am using vue-virtual-scroller for virtual list.

I have followed the steps mentioned in the documentation and made sure that:

Here's my code:

<template lang="pug">
DynamicScroller.e-solution-list__body(:items="items" :min-item-size="54" v-if="items.length && !solutionTable.loading" :emit-update="true" ref="scroller")
        template(#default="{ item, index, active }")
          DynamicScrollerItem(:item="item" :active="active" :data-index="index")
            .e-solution-list__row(:key="item.id" :class="{ 'e-solution-list__row--expanded': isExpanded(item.id), 'e-solution-list__row--mobile-border': !isExpanded(item.id) || !item.tags.length }")
</template>
<script lang="ts">
import { useInfiniteScroll } from '@vueuse/core'
 setup(props) {
    const columns = ref(SOLUTION_COLUMNS)
    const id = ref(props.problemId)
    const solutionTable = reactive({
      loading: false,
      loadMore: false,
      data: [],
      totalCount: 0,
      query: {
        sortBy: '-createdDate',
        skip: 0,
        limit: USE_CASE_LIMIT,
        text: '',
        popPaths: 'solutionProviderList,actors,sfCategories,sfSubCategories,sfIndustries,sfTechnologies,sfTags'
      }
    })
    const scroller = ref<HTMLElement>(null)
 //infinite scroll
    nextTick(() => {
      useInfiniteScroll(
        scroller,
        () => {
          getRelatedSolutions({
            skip: items.value.length,
            limit: USE_CASE_LIMIT,
            loadMore: true,
            isScrollTop: false,
            sortBy: sortBy.isAscending ? sortBy.key : `-${sortBy.key}`
          })
        },
        {
          distance: ITEM_HEIGHT * 2
        }
      )
    })

    
}


</script>

Despite following these steps, the infinite scroll functionality is not working as expected. The `useInfiniteScroll` callback function is not triggered when scrolling near the bottom of the element. I have tried the following approaches, but none of them resolved the issue:

  1. Ensuring the `ref` is properly assigned within the `DynamicScroller.e-solution-list__body` component.

  2. Accessing the scrollable element using `document.getElementById()` or `document.querySelector()` instead of a `ref`.

  3. Wrapping the `useInfiniteScroll` call in the `$nextTick` function to ensure the DOM is updated.

I would appreciate any insights or suggestions on how to troubleshoot this issue and get the infinite scroll working correctly. Thank you!


Solution

    1. The ref's value is null before the component is mounted. You have to defer initiating the infinite scroller to onMounted:
    import { ref, onMounted, defineComponent } from 'vue'
    
    export default defineComponent({
      //...
      setup(props) {
        // ...
        const scroller = ref<HTMLElement>(null)
        onMounted(() => {
          useInfiniteScroll(
            scroller,
            () => {
              getRelatedSolutions({
                //...
              })
            }
          )
        })
        return { 
          //...
          scroller // 👈 this is important if not using `<script setup>`
        }
      }
    })
    
    1. If you're not using <script setup>, your setup function has to return all reactive references used by <template> (as shown above).

    Important note: I noticed your <script> is not a <script setup> 1 and does not have a default export. If this is due to partial copy/pasting, ignore this note. But if that's what you're using, you should either:


    1 - <script setup> doesn't need a default export, as it takes the contents and treats it as if it was the contents of a setup() function, providing the necessary boilerplate for it in the compiled code.