How to wait for intersectionObserver API to have valid entry.boundingClientRect.y values? React

29 views Asked by At

I have a component on a page in react. It's sole job is to toggle light/dark state when the component intersects with the bottom of the viewport (either direction: up or down). The implementation I currently have works well for this. The implementation I have also works if I navigate to another page (say the about page) and then navigate back to the page with component in it. (Using react-router btw). It will render with the right state (light/dark) depending on whether the component is above or below the viewport when it is mounted. There is one condition I cant figure out though. When the component is above the bottom of the viewport (should be light mode at that point), and you refresh the page, I can't get it to render with the right darkmode state (light mode) when the page loads again. This is my current implementation:

const DarkModeIntersection = ({ darkmode, setDarkmode }) => {
  const ref = useRef(null);
  const [firstLoad, setFirstLoad] = useState(true);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (firstLoad) {
          setFirstLoad(false);
          return;
        }
        // Exit callback if intersection event is called on the top boundary
        if (entry.boundingClientRect.y < 200) return;

        // Ie scrolling down the page: Transition from dark - light
        if (entry.isIntersecting) {
          setDarkmode(false);
          document.body.style.background = "white";
          return;
        }

        // event triggered where - its not the top intersection
        //  its not scrolling down the page
        // Ie we are scrolling up - from light to dark;

        // if bounding client rect .y <
        console.log(entry.rootBounds.bottom);
        console.log(entry.boundingClientRect.y);
        if (entry.rootBounds.bottom < entry.boundingClientRect.y) {
          setDarkmode(true);
          document.body.style.background = "black";
        }
      },
      { threshold: 0, delay: 300 }
    );

    if (ref.current) {
      observer.observe(ref.current);
    }

    return () => {
      if (ref.current) {
        observer.unobserve(ref.current);
      }
    };
  }, [firstLoad]);

  return <div ref={ref} className={styles.intersection}></div>;
};

The problem with this is that when I refresh the page, the value of entry.boundingClientRect.y is some random number (not its actual value). How do I wait for the actual value to be available, and then set the darkmode state when it becomes available?

Would appreciate any help with this.

0

There are 0 answers