I am trying to implement an intersectionObserver to watch if a <Header/> isIntersecting, but specifically only with another <Component/>
MY ATTEMPT
import React, { useRef, useEffect } from "react";
import "./styles.css";
import Header from "./components/Header";
import SomeComponent from "./components/SomeComponent";
export default function App() {
const header = useRef(null);
const component = useRef(null);
const handleOverlap = (entries, observer) => {
entries.forEach((entry) => {
console.log(entry.isIntersecting);
});
};
useEffect(() => {
const options = {
root: component.current,
rootMargin: "10px",
threshold: 0.1
};
const observer = new IntersectionObserver(handleOverlap, options);
observer.observe(header.current);
}, []);
return (
<div className="App">
<Header ref={header} />
<div style={{ backgroundColor: "pink", height: "100vh" }}></div>
<SomeComponent ref={component} />
</div>
);
}
My desired result is to receive a true value if at point the user is scrolling and the header component intersects with the target component. I have set the root in the options object to a ref of the target component. I'm definitely missing some key logic somewhere. Any help would be great.
SANDBOX
https://codesandbox.io/s/friendly-shirley-u603gt?file=/src/App.js
Sharing my solution in case anyone should ever be in a similar situation.
My solution was to check for a scroll event as opposed to using the intersectionObserver I believe because my <Header/> is a fixed position element, it is taken out of the document flow and the observer can not detect a valid intersection between the two components.
Instead, my checkIfHeaderIsOverlapping function calls the .getBoundingClientRect() on the ref of each component, and applies some simple logic to detect an overlap/interection.
SOLUTION
import React, { useRef, useEffect, useState } from "react";
import "./styles.css";
import Header from "./components/Header";
import SomeComponent from "./components/SomeComponent";
export default function App() {
const [isOverlapping, setIsOverlapping] = useState(false);
console.log("is it true? =>", isOverlapping);
const header = useRef(null);
const component = useRef(null);
function checkIfHeaderIsOverlapping() {
if (header.current && component.current) {
const a = header.current.getBoundingClientRect();
const b = component.current.getBoundingClientRect();
if (a.top <= b.top + b.height && a.top + a.height > b.top) {
setIsOverlapping(true);
} else {
setIsOverlapping(false);
}
}
}
useEffect(() => {
function watchScroll() {
window.addEventListener("scroll", checkIfHeaderIsOverlapping);
}
watchScroll();
return () => {
window.removeEventListener("scroll", checkIfHeaderIsOverlapping);
};
});
return (
<div className="App">
<Header ref={header} />
<div style={{ backgroundColor: "pink", height: "100vh" }}></div>
<SomeComponent ref={component} />
<div style={{ backgroundColor: "green", height: "100vh" }}></div>
</div>
);
}
SANDBOX
https://codesandbox.io/s/friendly-shirley-u603gt?file=/src/App.js