DEV Community

Cover image for Lazy Loading React Components using intersection observer
Huzaima Khan
Huzaima Khan

Posted on • Originally published at huzaima.io

Lazy Loading React Components using intersection observer

Lazy loading react components is a way of deferring the rendering of components until they're needed. For below-the-fold content, it often makes sense to lazy load components, especially if they're detrimental to the performance if loaded upfront. I personally prefer to do lazy load heavy images and videos which appear below the fold. It helps increase core web vitals.

What is intersection observer?

An intersection observer is a JavaScript API that allows you to monitor when an element in your web page enters or exits the viewport. This can be useful for various purposes, such as triggering animations, lazy loading content, or implementing infinite scroll. The intersection observer API works by setting up a "callback" function that is executed whenever the target element intersects with the viewport, allowing you to respond to these events in your code.

Browser support for intersection observer

The intersection observer API is supported by most modern web browsers, including Chrome, Firefox, Safari, and Edge. However, it may not be supported by older browsers or some mobile browsers. You can check the specific browser support for the intersection observer API on caniuse.com, which tracks browser support for different web technologies. If your target browser don't support it, you can polyfill (add support for) the API in order to use it in your code.

Lazy Loading React Components using intersection observer (the hard way)

To use the intersection observer API in React, you can use the useRef hook to create a reference to the element you want to monitor and the useEffect hook to set up the observer. Here is an example of how you might do this:

function MyComponent() {
  // Create a reference to the element that we want to observe
  const targetElement = useRef(null);
  const [isInView, setIsInView] = useState(false);

  // Set up the intersection observer when the component mounts
  useEffect(() => {
    const observer = new IntersectionObserver(onIntersection, {});
    observer.observe(targetElement.current);

    // Clean up the observer when the component unmounts
    return () => observer.unobserve(targetElement.current);
  }, []);

  // This is the callback function that is executed whenever the
  // target element intersects with the viewport
  function onIntersection(entries) {
    // Do something with the intersection data, such as triggering
    // an animation or lazy loading content
    setIsInView(true);
  }

  return (
    <div ref={targetElement}>{isInView ? <VeryHeavyComponent /> : null}</div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this example, we used the useRef hook to create a reference to the element we want to observe and the useEffect hook to set up the intersection observer when the component mounts. When the target element intersects with the viewport, the onIntersection callback function is executed, allowing you to respond to the event in your code.

Make sure to clean up the IntersectionObserver you subscribed in useEffect. It's an important optimization of useEffect

Lazy Loading React Components using intersection observer (the easy way)

The react-intersection-observer package is a wrapper around the IntersectionObserver API and makes lazy loading less verbose and easy-peasy. Let's take a look at an example:

const Video = (props) => {
  const { ref, inView } = useInView({
    triggerOnce: true,
    fallbackInView: true,
  });

  return <div ref={ref}>{inView ? <video {...props} /> : null}</div>;
};
Enter fullscreen mode Exit fullscreen mode

In this example, the Video component is a wrapper around HTML's native video element. We only render video when it is in the viewport. It helps boost the performance of the page and core web vitals. You can pass various configurations to the useInView hook as described in the documentation. For example, you can specify a threshold value to control when the component should be considered visible or add a root margin to adjust the boundaries of the viewport.

In conclusion, using the IntersectionObserver API or react-intersection-observer package allows us to implement lazy loading in React components. This can improve the performance of our application by delaying the rendering of heavy components until they are actually needed. By using the useInView hook and monitoring when a component enters the viewport, we can efficiently lazy load our components and improve the user experience.

Top comments (1)

Collapse
 
pcelac profile image
Aleks

Lazy loading in React represents something else than described :)