JAVASCRIPT

Implement Lazy Loading and Animations with useIntersectionObserver Hook

Leverage the useIntersectionObserver hook in React to detect when an element enters or exits the viewport, enabling features like lazy loading images or scroll-triggered animations.

import React, { useRef, useState, useEffect } from 'react';

function useIntersectionObserver(options) {
  const [entry, setEntry] = useState(null);
  const targetRef = useRef(null);

  useEffect(() => {
    const node = targetRef.current;
    if (!node) return;

    const observer = new IntersectionObserver(([singleEntry]) => {
      setEntry(singleEntry);
    }, options);

    observer.observe(node);

    return () => {
      observer.disconnect();
    };
  }, [options]); // Re-run if options change

  return [targetRef, entry];
}

function LazyImage({ src, alt }) {
  const [imgRef, entry] = useIntersectionObserver({
    threshold: 0.1, // Trigger when 10% of the target is visible
    rootMargin: '0px 0px -100px 0px', // Start loading 100px before reaching bottom of viewport
  });
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    if (entry?.isIntersecting) {
      setIsVisible(true);
    }
  }, [entry]);

  return (
    <div ref={imgRef} style={{ height: '300px', background: '#eee', marginBottom: '20px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      {isVisible ? (
        <img src={src} alt={alt} style={{ maxWidth: '100%', maxHeight: '100%' }} />
      ) : (
        <p>Scroll down to load image...</p>
      )}
    </div>
  );
}

function IntersectionObserverDemo() {
  return (
    <div style={{ height: '200vh', padding: '20px' }}>
      <h1>Scroll Down to See Lazy Loading</h1>
      <div style={{ height: '800px' }}>
        <p>Some content above the image...</p>
      </div>
      <LazyImage 
        src="https://picsum.photos/600/300" 
        alt="A random beautiful landscape"
      />
      <div style={{ height: '800px' }}>
        <p>Some content below the image...</p>
      </div>
    </div>
  );
}

export default IntersectionObserverDemo;
How it works: This custom `useIntersectionObserver` hook provides a reactive way to detect when an element enters or exits the browser's viewport. It takes `IntersectionObserver` options and returns a ref to attach to the target element, along with the current `IntersectionObserverEntry`. In the `LazyImage` example, we use it to conditionally render an image only when it becomes visible in the viewport (or slightly before, thanks to `rootMargin`), effectively implementing lazy loading. This conserves bandwidth and improves initial page load performance.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs