intersection observer hook
by gbos
HTML
<div id="app"></div>
CSS
body {
background: white;
padding: 20px;
font-family: Arial;
}
React
const { useEffect, useState, useRef } = React;
const isIntersectionObserverSupported = 'IntersectionObserver' in window;
function useIsVisible () {
const [isVisible, setIsVisible] = useState(false);
const [hasBeenVisible, setHasBeenVisible] = useState(false);
const observerRef = useRef(null);
const ref = useRef(null);
useEffect(() => {
observerRef.current = new IntersectionObserver(([entry]) =>
setIsVisible(entry.isIntersecting)
);
}, []);
useEffect(() => {
if (isVisible && !hasBeenVisible) {
setHasBeenVisible(true);
}
}, [isVisible]);
useEffect(() => {
observerRef.current.observe(ref.current);
return () => {
observerRef.current.disconnect();
};
}, [ref]);
return {isVisible, hasBeenVisible, ref};
}
function Component ({index}) {
const {ref, isVisible, hasBeenVisible} = useIsVisible();
useEffect(() => {
console.log(`index ${index} visible: ${isVisible} ${hasBeenVisible}`);
}, [isVisible, hasBeenVisible]);
return <div style={{height: '60vh', backgroundColor: 'lightgrey', marginBottom: '10px', fontSize: '40px'}} ref={ref}>{index}</div>;
}
function App () {
return <div>
<Component index="aa"/>
<Component index="bb"/>
<Component index="cc"/>
<Component index="dd"/>
<Component index="ee"/>
</div>;
}
ReactDOM.render(<App />, document.querySelector("#app"))