maciekgrzybek / svelte-inview

A Svelte action that monitors an element enters or leaves the viewport.🔥
MIT License
749 stars 23 forks source link

"TypeError: 'observe' called on an object that does not implement interface IntersectionObserver." when calling event.detail.observe() #17

Closed Stijn-B closed 2 years ago

Stijn-B commented 2 years ago

Hello, I'm getting a TypeError when calling the event.detail.observer() function in an inview event callback:

Uncaught (in promise) TypeError: 'observe' called on an object that does not implement interface IntersectionObserver.

Context I use svelte-inview handleOnEnter to start an async function myAsyncFunction. Only 1 instance of myAsyncFunction should run at a time. So I thought about setting props={unobserverOnEnter: true} and then calling the event.detail.observe() method after myAsyncFunction is finished. This would disable the observer while myAsyncFunction is running and afterwards start observing again.

function handleOnEnter(event) {
    myAsyncFunction().then(() => {
        event.detail.observe(); // start observing the div again (this call results in the error)
    }
}

<div use:inview={{unobserveOnEnter: true}} on:enter={handleOnEnter} />

I'm not sure whether it's an issue or maybe I just misunderstood the event.detail.observe function.

Thanks for the great package and kind regards Stijn

maciekgrzybek commented 2 years ago

Hey @Stijn-B , thanks for creating an issue :) I'll take a look later today and will get back to you :)

maciekgrzybek commented 2 years ago

At a first glance, observe method requires an actual DOM element as an argument - so it knows what to observe. So if you could try doing something like this?

let myElement;
function handleOnEnter(event) {
    myAsyncFunction().then(() => {
        event.detail.observe(myElement);
    }
}

<div bind:this={myElement} use:inview={{unobserveOnEnter: true}} on:enter={handleOnEnter} />

bind:this saves a ref to the element (docs). Sorry, I didn't have time yet to properly test my theory. If you could try and let me know? If I'm right, I'll expose the node in the event.detail as well, so it will be easier to get it :)

Hope that helps :)

Stijn-B commented 2 years ago

@maciekgrzybek I tried it but the same error occurs

maciekgrzybek commented 2 years ago

Ok thanks for checking. I will check this and get back to you with the solution.

maciekgrzybek commented 2 years ago

Ok so I've found the culprit. If you use version 3 it will work for you. API changed a little bit, so you'll need to use it like this instead:

function handleOnEnter(event) {
    myAsyncFunction().then(() => {
        event.detail.observer.observe(event.detail.node);
    })
}

<div use:inview={{unobserveOnEnter: true}} on:enter={handleOnEnter} />

Let me know if you're still struggling :)