Join the Nature Wishlist Discord to get help, share your projects, and discuss JavaScript.
⚡️ ⏐ Performance Patterns
4. Import on Visibility

Import on Visibility

Load non-critical components when they are visible in the viewport


Overview

We just saw how we can dynamically import components base on user interaction. However, we can also dynamically import components based on their visibility within the viewport.

For example, if we wanted to show the listings on smaller viewports, not all listings are instantly visible to the user.

Instead, we can lazy-load the listings, and only load them when they're visible in the viewport when the user scrolls down.


Implementation

One way to dynamically import components on interaction, is by using the Intersection Observer API (opens in a new tab). There's a React hook called react-intersection-observer (opens in a new tab) that we can use to easily detect whether a component is visible in the viewport.

Lazy-loading the Footer component would result in something like this:

import { Suspense, lazy } from "react";
import { useInView } from "react-intersection-observer";
const Listing = lazy(() => import("./components/Listing"));
 
function ListingCard(props) {
  const { ref, inView } = useInView();
 
  return (
    <div ref={ref}>
      <Suspense fallback={<div />}>{inView && <Listing />}</Suspense>
    </div>
  );
}

Tradeoffs

Faster initial load: Dynamically importing modules reduces the initial bundle size - allowing for a smaller initial load since the client doesn't have to download and execute as much, saving bandwidth.

Layout shift: A layout shift can occur if your fallback component and the component that eventually gets rendered differ a lot in size.