2

In my next.js component layout I am trying to check when a modal window that contains the div #snipcart is on visible in the window.

I am trying to use the IntersectionObserver to check this but I'm not getting an output?

How can I check when div #snipcart on screen in my app?

 useEffect(() => {
    const cartTotal = document.querySelector('#cartTotal') !== null ? document.querySelector('#cartTotal').textContent.replace('£','') : ''
    const cartInvoiceNo = document.querySelector('#invoiceNo') !== null ? document.querySelector('#invoiceNo').textContent : ''
    
    if ((cartTotal &&!cartTotal.includes('}}')) && (cartInvoiceNo && !cartInvoiceNo.includes('}}'))) {
      setTagTotal(cartTotal)
      setTagInvoiceNo(cartInvoiceNo)
    }   

    let message = document.querySelector('#layout');

// INTERSECTION OBSERVER STUFF
const io = new IntersectionObserver(entries => {
   if(entries[0].isIntersecting) {
    console.log(entries);
  }
}, {
    threshold: [0]
});

// ELEMENTS TO OBSERVE
const blk1 = document.querySelector('#snipcart');

// START OBSERVING ELEMENTS
io.observe(blk1);
tom harrison
  • 3,273
  • 11
  • 42
  • 71
  • You could try checking all the entries instead of just the first one? i.e. change `if(entries[0].isIntersecting) { console.log(entries) }` to `entries.forEach(entry => { console.log(entry); }` – Shoejep Nov 06 '20 at 13:11
  • thanks, I now get intersecting: false, I believe it should return true as my layout component is covering the whole window and the `#snipcart' div is within this window, is a threshold of 0 correct? – tom harrison Nov 06 '20 at 13:39
  • thanks, this seems to work, however I would like to check for a div that doesn't exist until it's loaded and I get the error Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'., how can I prevent this error by checking if the element exists first? – tom harrison Nov 06 '20 at 13:47
  • Glad it works, threshold 0 means that as soon as they start intersecting. You can just do `if(element) { io.observe(element); }` or you could do something like [this](https://stackoverflow.com/a/35211286/3688864) and wait for the element to load. – Shoejep Nov 06 '20 at 16:45

1 Answers1

1

You should change your code so that it checks if any of the entries are intersecting instead of just the first one, i.e. change

if(entries[0].isIntersecting) 
{ 
    console.log(entries);
}

to

entries.forEach(entry => 
{ 
    console.log(entry);
});

You currently have threshold: [0] which means

The default is 0 (meaning as soon as even one pixel is visible, the callback will be run).

as explained here.


You should also check your element exists before observing.

if(element)
{
    io.observe(element);
}

or if you don't know when the element is going to exist, you can use the MutationObserver as explained here.

Shoejep
  • 4,414
  • 4
  • 22
  • 26