What is react-lazy-load-image-component?
The react-lazy-load-image-component package is a React component that provides lazy loading functionality for images. It helps improve performance by loading images only when they are in the viewport, reducing the initial load time and bandwidth usage.
What are react-lazy-load-image-component's main functionalities?
Basic Lazy Loading
This feature allows you to lazy load an image with a blur effect. The image will only load when it comes into the viewport, improving performance.
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
const App = () => (
<LazyLoadImage
alt={'Image Alt Text'}
height={200}
src={'https://example.com/image.jpg'} // use normal <img> attributes as props
width={200}
effect='blur'
/>
);
Placeholder Image
This feature allows you to specify a placeholder image that will be displayed while the main image is loading. This can enhance the user experience by providing a visual cue that an image is being loaded.
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
const App = () => (
<LazyLoadImage
alt={'Image Alt Text'}
height={200}
src={'https://example.com/image.jpg'}
width={200}
placeholderSrc={'https://example.com/placeholder.jpg'}
effect='blur'
/>
);
Custom Placeholder
This feature allows you to use a custom React component as a placeholder while the main image is loading. This provides more flexibility in designing the loading state.
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
const App = () => (
<LazyLoadImage
alt={'Image Alt Text'}
height={200}
src={'https://example.com/image.jpg'}
width={200}
placeholder={<div style={{ height: 200, width: 200, backgroundColor: '#ccc' }}>Loading...</div>}
effect='blur'
/>
);
Other packages similar to react-lazy-load-image-component
react-lazyload
react-lazyload is another popular package for lazy loading components and images in React. It provides a higher-order component and a hook for lazy loading, and it supports features like debounce and throttle. Compared to react-lazy-load-image-component, it offers more general-purpose lazy loading capabilities but may require more setup for image-specific use cases.
react-intersection-observer
react-intersection-observer is a React implementation of the Intersection Observer API, which can be used to lazy load images and other components. It provides a hook and a render prop for observing when elements enter or leave the viewport. This package is more flexible and can be used for a variety of lazy loading scenarios, but it requires more manual setup for image-specific use cases compared to react-lazy-load-image-component.
react-lazy-load
react-lazy-load is a simple React component for lazy loading images and other components. It provides basic lazy loading functionality with minimal configuration. While it is easy to use, it lacks some of the advanced features like custom placeholders and effects that react-lazy-load-image-component offers.
React Lazy Load Image Component
React Component to lazy load images and other components/elements. Supports IntersectionObserver and includes a HOC to track window scroll position to improve performance.
"An easy-to-use performant solution to lazy load images in React"
Features
- Includes two components (
LazyLoadImage
and LazyLoadComponent
) and a HOC (trackWindowScroll
) which adds scroll position tracking to any component you wish. - Handles scroll events, resize events and re-renders that might change the position of the components. And, of course, above-the-fold on initial render.
- Placeholder by default with the same size of the image/component.
- A custom placeholder component or image can be specified.
- Built-in on-visible effects (blur, black and white and opacity transitions).
- threshold is set to 100px by default and can be modified.
beforeLoad
and afterLoad
events.debounce
and throttle
included by default and configurable.- Uses IntersectionObserver for browsers that support it.
- Server Side Rendering (SSR) compatible.
Installation
$ yarn add react-lazy-load-image-component
$ npm i --save react-lazy-load-image-component
LazyLoadImage
usage
import React from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
const MyImage = ({ image }) => (
<div>
<LazyLoadImage
alt={image.alt}
height={image.height}
src={image.src} // use normal <img> attributes as props
width={image.width} />
<span>{image.caption}</span>
</div>
);
export default MyImage;
Props
Prop | Type | Default | Description |
---|
afterLoad | Function | | Function called after the image has been completely loaded. |
beforeLoad | Function | | Function called right before the placeholder is replaced with the image element. |
delayMethod | String | throttle | Method from lodash to use to delay the scroll/resize events. It can be throttle or debounce . |
delayTime | Number | 300 | Time in ms sent to the delayMethod. |
effect | String | | Name of the effect to use. Please, read next section with an explanation on how to use them. |
placeholder | ReactClass | <span> | React element to use as a placeholder. |
placeholderSrc | String | | Image src to display while the image is not visible or loaded. |
threshold | Number | 100 | Threshold in pixels. So the image starts loading before it appears in the viewport. |
useIntersectionObserver | Boolean | true | Whether to use browser's IntersectionObserver when available. |
visibleByDefault | Boolean | false | Whether the image must be visible from the beginning. |
wrapperClassName | String | | In some occasions (for example, when using a placeholderSrc) a wrapper span tag is rendered. This prop allows setting a class to that element. |
... | | | Any other image attribute |
Using effects
LazyLoadImage
includes several effects ready to be used, they are useful to add visual candy to your application, but are completely optional in case you don't need them or want to implement you own effect.
They rely on CSS and the corresponding CSS file must be imported:
import React from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
const MyImage = ({ image }) => (
<LazyLoadImage
alt={image.alt}
effect="blur"
src={image.src} />
);
The current available effects are:
blur
: renders a blurred image based on placeholderSrc
and transitions to a non-blurred one when the image specified in the src is loaded.
black-and-white
: renders a black and white image based on placeholderSrc
and transitions to a colorful image when the image specified in the src is loaded.
opacity
: renders a blank space and transitions to full opacity when the image is loaded.
LazyLoadComponent
usage
import React from 'react';
import { LazyLoadComponent } from 'react-lazy-load-image-component';
import { ArticleContent, ArticleComments } from 'my-app';
const Article = ({ articleId }) => (
<div>
<ArticleContent id={articleId} />
<LazyLoadComponent>
<ArticleComments id={articleId} />
</LazyLoadComponent>
</div>
);
export default Article;
Props
Prop | Type | Default | Description |
---|
afterLoad | Function | | Function called after the component has been rendered. |
beforeLoad | Function | | Function called right before the component is rendered. |
delayMethod | String | throttle | Method from lodash to use to delay the scroll/resize events. It can be throttle or debounce . |
delayTime | Number | 300 | Time in ms sent to the delayMethod from lodash. |
placeholder | ReactClass | <span> | React element to use as a placeholder. |
threshold | Number | 100 | Threshold in pixels. So the component starts loading before it appears in the viewport. |
useIntersectionObserver | Boolean | true | Whether to use browser's IntersectionObserver when available. |
visibleByDefault | Boolean | false | Whether the component must be visible from the beginning. |
Using trackWindowScroll
HOC to improve performance
When you have many elements to lazy load in the same page, you might get poor performance because each one is listening to the scroll/resize events. In that case, it's better to wrap the deepest common parent of those components with a HOC to track those events (trackWindowScroll
).
For example, if we have an App
which renders a Gallery
, we would wrap the Gallery
component with the HOC.
import React from 'react';
import { LazyLoadImage, trackWindowScroll }
from 'react-lazy-load-image-component';
const Gallery = ({ images, scrollPosition }) => (
<div>
{images.map((image) =>
<LazyLoadImage
key={image.key}
alt={image.alt}
height={image.height}
// Make sure to pass down the scrollPosition,
// this will be used by the component to know
// whether it must track the scroll position or not
scrollPosition={scrollPosition}
src={image.src}
width={image.width} />
)}
</div>
);
export default trackWindowScroll(Gallery);
You must set the prop scrollPosition
to the lazy load components. This way, they will know the scroll/resize events are tracked by a parent component and will not subscribe to them.
Props
LazyLoadImage
Prop | Type | Default | Description |
---|
scrollPosition | Object | | Object containing x and y with the curent window scroll position. Required. |
afterLoad | Function | | Function called after the image has been rendered. |
beforeLoad | Function | | Function called right before the image is rendered. |
placeholder | ReactClass | <span> | React element to use as a placeholder. |
threshold | Number | 100 | Threshold in pixels. So the image starts loading before it appears in the viewport. |
visibleByDefault | Boolean | false | Whether the image must be visible from the beginning. |
... | | | Any other image attribute |
Component wrapped with trackWindowScroll
(in the example, Gallery
)
Prop | Type | Default | Description |
---|
delayMethod | String | throttle | Method from lodash to use to delay the scroll/resize events. It can be throttle or debounce . |
delayTime | Number | 300 | Time in ms sent to the delayMethod from lodash. |
useIntersectionObserver | Boolean | true | Whether to use browser's IntersectionObserver when available. |
Notice you can do the same replacing LazyLoadImage
with LazyLoadComponent
.
When to use visibleByDefault
?
The prop visibleByDefault
makes the LazyLoadImage to behave like a normal <img>
. Why is it useful, then?
Imagine you are going to lazy-load an image you have already loaded in the same page. In that case, there is no need to lazy-load it because it's already stored in the cache of the user's browser. You can directly display it.
Maybe the following code snippet will make it more clear:
import React from 'react';
import { LazyLoadImage, trackWindowScroll }
from 'react-lazy-load-image-component';
const Gallery = ({ images, scrollPosition }) => (
<div>
// We are loading landscape.jpg here
<img src="/landscape.jpg" alt="Beautiful landscape" />
{images.map((image) =>
<LazyLoadImage
key={image.key}
alt={image.alt}
scrollPosition={scrollPosition}
src={image.src}
// If the image we are creating here has the same src than before,
// we can directly display it with no need to lazy-load.
visibleByDefault={image.src === '/landscape.jpg'} />
)}
</div>
);
export default trackWindowScroll(Gallery);
Demos
Common errors
Warning: setState(...): Can only update a mounted or mounting component.
That warning might appear if there are two components using trackWindowScroll
at the same time. Notice it's not possible to have a LazyLoadImage/LazyLoadComponent inside another LazyLoadComponent for now. Also, make sure you are passing down scrollPosition
to all components wrapped inside trackWindowScroll
.