DEV Community

Oliver Reed
Oliver Reed

Posted on

Optimizing Performance with React LazyLoad: Implementing Lazy Loading

React LazyLoad is a lightweight library for implementing lazy loading of components and images in React applications. It helps improve initial page load performance by deferring the loading of content until it's needed or about to enter the viewport. This guide walks through implementing lazy loading using React LazyLoad with React, covering image lazy loading, component lazy loading, and performance optimization patterns. This is part 23 of a series on using React LazyLoad with React.

Prerequisites

Before you begin, ensure you have:

  • Node.js version 14.0 or higher
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) with hooks support
  • Basic understanding of React hooks (useState, useEffect)
  • Familiarity with JavaScript/TypeScript

Installation

Install React LazyLoad using your preferred package manager:

npm install react-lazyload
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add react-lazyload
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add react-lazyload
Enter fullscreen mode Exit fullscreen mode

Your package.json should include:

{
  "dependencies": {
    "react-lazyload": "^3.2.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

React LazyLoad requires minimal setup. No additional configuration is needed beyond installation.

First Example / Basic Usage

Let's create a simple lazy-loaded image component. Create src/LazyImage.jsx:

// src/LazyImage.jsx
import React from 'react';
import LazyLoad from 'react-lazyload';

function LazyImage({ src, alt, height = 200 }) {
  return (
    <LazyLoad height={height} offset={100}>
      <img 
        src={src} 
        alt={alt}
        style={{ width: '100%', height: 'auto' }}
      />
    </LazyLoad>
  );
}

export default LazyImage;
Enter fullscreen mode Exit fullscreen mode

Now, use it in your app:

// src/App.jsx
import React from 'react';
import LazyImage from './LazyImage';
import './App.css';

function App() {
  return (
    <div className="App">
      <h1>Lazy Loaded Images</h1>
      <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
        <LazyImage 
          src="https://picsum.photos/800/600?random=1" 
          alt="Image 1"
          height={600}
        />
        <LazyImage 
          src="https://picsum.photos/800/600?random=2" 
          alt="Image 2"
          height={600}
        />
        <LazyImage 
          src="https://picsum.photos/800/600?random=3" 
          alt="Image 3"
          height={600}
        />
      </div>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This creates lazy-loaded images that only load when they're about to enter the viewport.

Understanding the Basics

React LazyLoad uses Intersection Observer API to detect when elements enter the viewport:

  • LazyLoad: Wrapper component that enables lazy loading
  • height: Expected height of the content (helps prevent layout shift)
  • offset: Distance from viewport to start loading (in pixels)
  • placeholder: Content to show while loading

Key concepts:

  • Viewport Detection: Uses Intersection Observer to detect when elements are visible
  • Offset: Controls when loading starts (before element enters viewport)
  • Placeholder: Shows content while the actual content is loading
  • Height: Prevents layout shift by reserving space

Here's an example with a placeholder:

// src/LazyImageWithPlaceholder.jsx
import React from 'react';
import LazyLoad from 'react-lazyload';

function LazyImageWithPlaceholder({ src, alt }) {
  const placeholder = (
    <div 
      style={{
        height: '400px',
        backgroundColor: '#f0f0f0',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center'
      }}
    >
      Loading...
    </div>
  );

  return (
    <LazyLoad 
      height={400} 
      offset={200}
      placeholder={placeholder}
    >
      <img 
        src={src} 
        alt={alt}
        style={{ width: '100%', height: 'auto' }}
      />
    </LazyLoad>
  );
}

export default LazyImageWithPlaceholder;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive image gallery with lazy loading:

// src/ImageGallery.jsx
import React, { useState } from 'react';
import LazyLoad from 'react-lazyload';

function ImageGallery() {
  const [images] = useState([
    { id: 1, url: 'https://picsum.photos/800/600?random=1', title: 'Image 1' },
    { id: 2, url: 'https://picsum.photos/800/600?random=2', title: 'Image 2' },
    { id: 3, url: 'https://picsum.photos/800/600?random=3', title: 'Image 3' },
    { id: 4, url: 'https://picsum.photos/800/600?random=4', title: 'Image 4' },
    { id: 5, url: 'https://picsum.photos/800/600?random=5', title: 'Image 5' },
    { id: 6, url: 'https://picsum.photos/800/600?random=6', title: 'Image 6' },
    { id: 7, url: 'https://picsum.photos/800/600?random=7', title: 'Image 7' },
    { id: 8, url: 'https://picsum.photos/800/600?random=8', title: 'Image 8' },
    { id: 9, url: 'https://picsum.photos/800/600?random=9', title: 'Image 9' },
    { id: 10, url: 'https://picsum.photos/800/600?random=10', title: 'Image 10' }
  ]);

  const placeholder = (
    <div 
      style={{
        width: '100%',
        height: '400px',
        backgroundColor: '#e0e0e0',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        borderRadius: '8px'
      }}
    >
      <div style={{ color: '#999' }}>Loading image...</div>
    </div>
  );

  return (
    <div style={{ padding: '20px' }}>
      <h2>Image Gallery</h2>
      <div 
        style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
          gap: '20px'
        }}
      >
        {images.map((image) => (
          <LazyLoad
            key={image.id}
            height={400}
            offset={100}
            placeholder={placeholder}
            once={true}
          >
            <div
              style={{
                borderRadius: '8px',
                overflow: 'hidden',
                boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
              }}
            >
              <img
                src={image.url}
                alt={image.title}
                style={{
                  width: '100%',
                  height: '400px',
                  objectFit: 'cover',
                  display: 'block'
                }}
                onLoad={() => console.log(`Image ${image.id} loaded`)}
              />
              <div style={{ padding: '12px', backgroundColor: 'white' }}>
                <h3 style={{ margin: 0 }}>{image.title}</h3>
              </div>
            </div>
          </LazyLoad>
        ))}
      </div>
    </div>
  );
}

export default ImageGallery;
Enter fullscreen mode Exit fullscreen mode

Here's an example with lazy-loaded components:

// src/LazyComponentExample.jsx
import React, { Suspense, lazy } from 'react';
import LazyLoad from 'react-lazyload';

// Lazy load a heavy component
const HeavyComponent = lazy(() => import('./HeavyComponent'));

function LazyComponentExample() {
  return (
    <div style={{ padding: '20px' }}>
      <h2>Lazy Loaded Components</h2>
      <div style={{ marginBottom: '1000px' }}>
        <p>Scroll down to see the lazy-loaded component...</p>
      </div>

      <LazyLoad height={400} offset={200}>
        <Suspense fallback={<div>Loading component...</div>}>
          <HeavyComponent />
        </Suspense>
      </LazyLoad>
    </div>
  );
}

export default LazyComponentExample;
Enter fullscreen mode Exit fullscreen mode

This example demonstrates:

  • Image lazy loading with placeholders
  • Grid layout for image gallery
  • Loading callbacks
  • Component lazy loading with React.lazy
  • Offset configuration for better UX
  • Once prop to prevent re-loading

Common Issues / Troubleshooting

  1. Images not loading: Ensure you've set the height prop correctly. Without it, LazyLoad may not detect when to load content. Also check that your images have valid URLs.

  2. Layout shift: Always provide the height prop to reserve space for content. This prevents the page from jumping when content loads.

  3. Content loading too early/late: Adjust the offset prop. A larger offset loads content earlier, while a smaller offset loads it later.

  4. Performance issues: Use the once prop to prevent re-loading content that has already been loaded. This is especially useful for scrollable lists.

  5. Intersection Observer not supported: React LazyLoad falls back to scroll events in older browsers. Ensure your target browsers support Intersection Observer or the fallback behavior.

Next Steps

Now that you understand React LazyLoad:

  • Explore advanced features like debounce and throttle
  • Implement lazy loading for different content types (videos, iframes)
  • Learn about performance monitoring and optimization
  • Add loading states and error handling
  • Explore intersection observer API directly
  • Check the official repository: https://github.com/jasonslyvia/react-lazyload
  • Look for part 24 of this series for more advanced topics

Summary

You've learned how to implement lazy loading with React LazyLoad to improve your application's performance. The library provides a simple API for deferring content loading until it's needed, helping reduce initial page load times and improve user experience.

SEO Keywords

react-lazyload
React lazy loading
react-lazyload tutorial
React image lazy load
react-lazyload installation
React performance optimization
react-lazyload example
React lazy load component
react-lazyload setup
React viewport detection
react-lazyload images
React intersection observer
react-lazyload performance
React lazy loading images
react-lazyload getting started

Top comments (0)