Implement infinite scrolling in Vue 3

useIntersectionObserver

Idea inspired byinfinite scrolling in vue. In this example, we simplify the implementation by using vueuse intersection observer hook.

Demo

scroll inside this container
item 0
item 1
item 2
item 3
item 4
item 5
item 6
item 7
item 8
item 9
Last item / you saw me
intersect: false
scroll position: 0
<div ref="scrollContainer">
.
.
<div ref="targetEl">now u see me</div>
</div>
<script setup lang='ts'>
import { useIntersectionObserver } from '@vueuse/core'

const items = [...Array(10).keys()] 
const fakeData = [...Array(5).keys()] 

// get element reference
const targetEl = ref<HTMLElement | null>(null) 
const scrollContainer = ref<HTMLElement | null>(null)

const targetIsVisible = ref(false)
const text = ref('Last item / you saw me')

// useIntersectionObserver
useIntersectionObserver(
  targetEl, 👈 
  ([{ isIntersecting }]) => {
    targetIsVisible.value = isIntersecting
  }
)

// watchEffect return a stop handler
const stopWatchInifiteScroll = watchEffect(() => {
  if (targetIsVisible.value) {
    loading.value = true

    // scenario: fetch more data
    setTimeout(() => {
      items.value.push(...fakedata)
      loading.value = false
      // when loaded, scroll up a bit 
      // to keep the user in the same scroll position
      scrollContainer.value!.scrollBy(0, -100)
    }, 1000)
  }
})

// condition to stop the watcher
watchEffect(() => {
  if (items.value.length > 60) {
    stopWatchInifiteScroll()
    text.value = 'stop, that\'s a lot of calls'
  }
})

This is a very straightforward implementation. The only thing to note is that we need to use theuseIntersectionObserverhook to watch the visibility of the target element. Also, you can useuseScrollto watch the scroll position when it reaches the bottom.

Happy Wednesday!💖

Made withby leovoon