React Image and Lazy-Loading Libraries
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. See the section bibliography for the reference material consulted while preparing these pages. |
Baseline date: 2026-10-07. Versions are the latest on npm on that date. Since browsers lazy-load natively, most of these libraries are now optional. This page says what each does, how active it is and what to use instead. The React fundamentals are in the React section, and the native attributes are in native HTML images.
The native baseline
export function Cover({ src, srcSet, alt, width, height }: CoverProps) {
return (
<img src={src} srcSet={srcSet} sizes="(min-width: 60em) 20vw, 50vw"
alt={alt} width={width} height={height} loading="lazy" decoding="async" />
);
}
React passes loading, decoding and fetchPriority straight to the DOM. For the LCP image, drop loading="lazy".
That covers lazy loading, responsive sources and layout shift without a dependency. What it lacks is a fallback chain,
a custom trigger distance and a built-in effect, which is what the libraries add.
react-lazyload
react-lazyload (3.2.1) wraps content in a LazyLoad component that renders it
when it scrolls near the viewport.
import LazyLoad from 'react-lazyload';
<LazyLoad height={300} offset={200} once placeholder={<div className="skeleton" />}>
<img src={url} alt={alt} width={200} height={300} />
</LazyLoad>
It works with any content, not only images, and it uses scroll listeners rather than an IntersectionObserver by default. Activity is low. Prefer native lazy loading for images, or IntersectionObserver for other content.
react-image
react-image (4.1.0) offers an Img component and a useImage hook with a list of
sources to try in order, and loader and fallback elements. It has not had a release since 2023.
import { useImage } from 'react-image';
function Cover({ srcList }: { srcList: string[] }) {
const { src, isLoading, error } = useImage({ srcList, useSuspense: false });
if (isLoading) return <div className="skeleton" />;
if (error) return <div className="no-cover">No cover</div>;
return <img src={src} alt="" />;
}
The fallback chain is useful for user avatars (try the user’s image, then a generated one). It does not do responsive
images: it picks one URL, so you lose srcset. Verify that the version still works with your React major version.
react-lazy-load-image-component
react-lazy-load-image-component (1.6.3) provides
LazyLoadImage with a built-in placeholder, an effect (blur, black and white, opacity), and a trackWindowScroll HOC for
many images in a scrolling container.
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
<LazyLoadImage src={url} alt={alt} width={200} height={300} effect="blur" placeholderSrc={tinyUrl} />
The blur effect shows the image blurred while the file loads, and a placeholderSrc can be a small image or a data URL
decoded from a BlurHash, see BlurHash in the browser.
A small IntersectionObserver hook
When you need to control the trigger (a carousel, an infinite list, a video), a hook is a dozen lines and has no dependency:
import { useEffect, useRef, useState } from 'react';
export function useInView<T extends Element>(rootMargin = '200px') {
const ref = useRef<T>(null);
const [inView, setInView] = useState(false);
useEffect(() => {
const node = ref.current;
if (!node) return;
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) { setInView(true); observer.disconnect(); }
}, { rootMargin });
observer.observe(node);
return () => observer.disconnect();
}, [rootMargin]);
return [ref, inView] as const;
}
Reference: MDN Intersection Observer API.
Which to use
| Option | Status | Needed? | When to choose it |
|---|---|---|---|
Native |
Browser feature |
Default |
Almost always. No dependency, responsive images, works with SSR. |
react-lazyload 3.2.1 |
Low activity |
Rarely |
Lazy-rendering non-image components with a scroll container, if you are already using it. |
react-image 4.1.0 |
No release since 2023 |
Sometimes |
Fallback chains for user-provided images. Check compatibility with your React version. |
react-lazy-load-image-component 1.6.3 |
Check the repository for recent activity |
Sometimes |
A ready-made blur or opacity effect over the placeholder, with minimal code. |
IntersectionObserver hook |
Browser feature |
When native is not enough |
Custom triggers and non-image content. |
|
Maintained with the framework |
In Next.js apps |
See Next.js Image. |
Whatever you choose, give every image width and height (or an aspect ratio) and use an optimised format. The libraries
only decide when to load.