javascriptreactjsintersection-observer

IntersectionObserver callback is being run even if the target isnt on the viewport


I am trying to execute a function when an element is visible in the viewport but the callback is running even if the element is wayyy below.

this is App.jsx

import {useState,useEffect,useRef} from 'react';
import Rect from "./Rect.jsx"

export function App(props) {
  const [rects,setRects]=useState([])
  const refer=useRef(null)
  const observer=useRef()
  useEffect(()=>{
    for (let i=0;i<50;i++){
      (i!==40)?setRects((reacts)=>[...reacts,<Rect index={i}/>]):setRects((reacts)=>[...reacts,<Rect index={i} ref={refer}/>])
    }
    observer.current=new IntersectionObserver((data)=>{
      alert(data[0].isIntersecting)
    },{threshold:1})
  },[])

//This below comment works as said in the docs
//observer.current=new IntersectionObserver((data)=>{
//    if (data[0].isIntersecting)
//    alert(data[0].isIntersecting)
//},{threshold:1})

  useEffect(()=>{
    if (refer.current){
      observer.current.observe(refer.current)
    }
  })
//},[])
// if you put an empty array here then the callback isnt run even if the element is visible
  
return (
    <div className='App'>
      <h1>Hello React.</h1>
      {rects.map((rect)=>rect)}
    </div>
  );
}

this is Rect.jsx

import { forwardRef } from "react";

const Rect=forwardRef((props,ref)=>{
  return (props.index==40)? <div style={{backgroundColor:"red",height:"20px",width:"20px"}} ref={ref}> </div>:<div style={{backgroundColor:"black",height:"20px",width:"20px"}}> </div>
})
export default Rect

edit: I read the docs and found that the commented is the intended way but why is the callback function running at start without anything even being intersected

playground


Solution

  • Well i was just not understanding how the callbacks function is executed. If anyone is also wondering why that happens the callback function is supposed to be called whenever the intersection is changed like if it goes from being visible to invisible then it will execute and if it goes from being invisible to visible it executes. And from what I understand at first the function is running at first is cuz the element being invisible while rendering for the first time as the change in intersection.