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:
The ref
is correctly defined using the ref()
function in my JavaScript code.
The ref
is assigned to the scrollable element within the DynamicScroller.e-solution-list__body
component, which I'm using in my template.
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:
Ensuring the `ref` is properly assigned within the `DynamicScroller.e-solution-list__body` component.
Accessing the scrollable element using `document.getElementById()` or `document.querySelector()` instead of a `ref`.
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!
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>`
}
}
})
<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:
setup
function in export default { /* code here */ }
setup
function in export default defineComponent({ /* code here */ })
(recommended, for typescript).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.