How to build an IntersectionObserver in Composition API?

Viewed 951

I am trying to implement an IntersectionOberver that will change the url when the viewport is moved into a new section. I found This thread and now trying to get it to work in vue 3 compositon api.

I'm trying to implement the script in my index.vue file, which is the parent of all other vue components:

<template>
  <div class="container">
    <navbar></navbar>
    <social-media-bar></social-media-bar>
    <main>
      <home></home>
      <news></news>
      <vision></vision>
      <event-section></event-section>
      <artwork></artwork>
      <about></about>
      <donate></donate>
      <contact></contact>
      <partners></partners>
    </main>
    <footer-component></footer-component>
  </div>
</template>


<script setup>
import ... // component imports
import {onMounted, reactive} from "vue";
import router from "../js/router";

const state = reactive({
    sectionObserver: null
})

const sectionObserveHandler = (entries) => {
    for (const entry of entries) {
        if (entry.isIntersecting) {
            router.push({name: 'news', hash: '#news'})
        }
    }
}
  
const observeSections = () => {
    const options = {
        rootMargin: '0px 0px',
        threshold: 0
    }
    state.sectionObserver = new IntersectionObserver(sectionObserveHandler, options)
    const sections = document.querySelectorAll('.section')
    sections.forEach(section =>{
        state.sectionObserver.observe(section)
    })
}

onMounted(() => {
    observeSections()
})
</script>

Basically, what I want for now is to change the url to .../#news when the viewport is scrolled to the next section.

When I start the web app, it works without error messages, but no url change occurs upon scrolling down to sections.

What am I doing wrong?

What I've noticed is that Phpstorm is telling me at this line:

state.sectionObserver = new IntersectionObserver(sectionObserveHandler, options)

that:

Assigned expression type IntersectionObserver is not assignable to type UnwrapRef<null> ...   Type IntersectionObserver is not assignable to type null extends ShallowRef<infer V> ? V : (null extends Ref<infer V> ? UnwrapRefSimple<V> : UnwrapRefSimple<null>)     Type IntersectionObserver is not assignable to type null extends Ref<infer V> ? UnwrapRefSimple<V> : UnwrapRefSimple<null>

I've changed state.sectionObserver to string, integer or array but the error persists. Not sure if this is relevant to make this work though since browser seems to ignore it.

1 Answers

Figured it out with the help of This great tutorial by Kevin Powell.

Had to put this into my index.vue's script setup tags:

onMounted(() => {
    const sections = document.querySelectorAll('section')
    const options = {
        threshold: 0.5
    }
    const observer = new IntersectionObserver(function(entries, observer) {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                console.log(entry.target)
            }
        })
    }, options)
    sections.forEach(section => {
        observer.observe(section)
    })
})
Related