JAVASCRIPT
Detect Element Visibility with a Custom useIntersectionObserver Hook
Implement features like lazy loading images, infinite scrolling, or scroll-triggered animations by creating a custom React hook that utilizes the Intersection Observer API.
import React, { useRef, useState, useEffect } from 'react';
const useIntersectionObserver = (options) => {
const [entry, setEntry] = useState(null);
const targetRef = useRef(null);
useEffect(() => {
const node = targetRef.current; // DOM Node to observe
if (!node) return;
const observer = new IntersectionObserver(([entry]) => {
setEntry(entry);
}, options);
observer.observe(node);
return () => {
observer.disconnect();
};
}, [options?.rootMargin, options?.threshold, options?.root]); // Re-create observer if options change
return [targetRef, entry];
};
// Example Usage:
const LazyImage = ({ src, alt }) => {
const [imgRef, entry] = useIntersectionObserver({ threshold: 0.1 });
const isVisible = entry?.isIntersecting;
return (
<div
ref={imgRef}
style={{
minHeight: '200px', // Placeholder height to show intersection
backgroundColor: '#f0f0f0',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '20px',
border: '1px solid #ddd'
}}
>
{isVisible ? (
<img src={src} alt={alt} style={{ maxWidth: '100%', maxHeight: '200px' }} />
) : (
<p>Scroll down to load image...</p>
)}
</div>
);
};
const App = () => (
<div style={{ padding: '20px', height: '150vh' }}>
<h2>Scroll down to see lazy loading:</h2>
<p style={{ height: '50vh' }}>Scroll placeholder...</p>
<LazyImage src="https://via.placeholder.com/400x200?text=Loaded+Image+1" alt="Placeholder Image 1" />
<LazyImage src="https://via.placeholder.com/400x200?text=Loaded+Image+2" alt="Placeholder Image 2" />
<LazyImage src="https://via.placeholder.com/400x200?text=Loaded+Image+3" alt="Placeholder Image 3" />
</div>
);
How it works: This custom hook `useIntersectionObserver` provides an easy way to detect when a DOM element enters or exits the viewport. It leverages the browser's native Intersection Observer API. The hook returns a `ref` to attach to the target element and an `entry` object containing details about the intersection (like `isIntersecting`). This is extremely useful for implementing performance optimizations like lazy loading images/components, infinite scrolling, or triggering animations when an element becomes visible.