Skip to content

How to Implement Lazy Loading with Infinite Scroll

One of the major challenges we face as frontend developers is to efficiently manage large sets of data. “Efficiently” here means managing the data in a way that doesn’t affect the user experience negatively. The common way of handling this is with Pagination but the problem with pagination is that it becomes clunky and delivers a poor user experience as the data grows.

In this guide, we’ll use lazy loading which is better and more friendly than using the conventional custom loading with hooks, and then we will use the user-friendly substitute for pagination, infinite scroll, to solve this challenge.

You need to have the following to flow with this guide:

  • Knowledge of JavaScript and React
  • Nodejs >=v14 installed

We will be implementing a card component and populating it with data so we can test the infinite scrolling. The complete code is on Codesandbox.

Let’s set up our react application by running the command below:

npx create-react-app lazy-loading-infinite-scroll

We will be using the react-bootstrap package for styling our card components. Install it by running this command on your terminal:

npm install react-bootstrap bootstrap

Create a component folder from the src directory and create a CardComponent.jsx file. Run this command to do that:

cd src
mkdir components && cd components
touch CardComponent.jsx
Code language: CSS (css)

Add this code snippet to CardComponent.jsx

//CardComponent.jsx
import { Card, Button, Container, Col, Row } from 'react-bootstrap'
export default function CardComponent() {
    return (
        <Container>
            <Row>
                <Col md={4}>
                    <Card style={{ width: '18rem' }}>
                        <Card.Img variant="top" src="https://images.unsplash.com/photo-1652512456007-e16ac46f1879?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1100&q=80" />
                        <Card.Body>
                            <Card.Title>card title</Card.Title>
                            <Card.Text>
                                this is an infinite scroll Up
                            </Card.Text>
                            <Button variant="primary">Up</Button>
                        </Card.Body>
                    </Card>
                </Col>
            </Row>
        </Container>
    )
}
Code language: JavaScript (javascript)

Here, we use react-bootstrap components to implement our Card Component. If you’ve noticed, we are not importing React, cause it’s not needed anymore.

Let’s head over to App.js and register our card component. Add the code snippet below:

//App.js
import 'bootstrap/dist/css/bootstrap.min.css';
import { lazy, Suspense } from 'react'

const CardComponent = lazy(() => import("./components/CardComponent"))
    
function App() {
    return (
    <div>
        <h1>React Lazy Loading with Infinite Scroll</h1>
        <Suspense fallback={<div>isLoading...</div>}>
            <CardComponent />
        </Suspense>
    </div>
    );
}
export default App;
Code language: JavaScript (javascript)

Firstly, we start by importing bootstrap CSS so it can be accessed globally in the project. Next, we use the React.lazy function from React which takes a function that calls a dynamic import(). This function must return a Promise which resolves to a module with a default export containing a React component. The lazy component (CardComponent in our case) will then be rendered inside the Suspense Component. The Suspense component allows us to have a fallback function that will be used to render a loader before the lazy components finish loading.

Let’s now run our app. Run this command on your terminal

npm run start 

You should see something like this:

If you’ve gotten to this stage, you’re Awesome! Now we’ve handled Lazy loading, let’s implement Infinite scroll.

Now that lazy loading is implemented on the Card component, we will implement infinite scroll for the cards, such that once the user reaches the bottom of the page, it automagically adds datasets or makes an API call without the need for pagination buttons.

First, we will create some mock data for our cards. This will be the dataset that will be used to loop through and display on the Card components. Create a mock.js file in the source directory and paste these lines of code

//mock.js
export const cardData = [{
    title: "card title",
    buttonName: "Down",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "Up",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "Left",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "right",
     description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "right",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "right",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "right",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "right",
    description: "this is an infinite scroll"
},
{
    title: "card title",
    buttonName: "right",
    description: "this is an infinite scroll"
}
]
    
Code language: JavaScript (javascript)

Next, navigate to App.js and import the mock data. Modify the App.js and add this line

//App.js
import { cardData } from './mock';
Code language: JavaScript (javascript)

Next, we will pass cardData as props to our CardWrapper Component. Update this line in App.js with this

//App.js
<CardComponent cardData={cardData} />
Code language: HTML, XML (xml)

Now we have passed our data to the Card component, let’s implement the infinite scroller.

We will be using an external react library called react-infinite-scroller.

First, we need to install the package. To do that run the command below

npm install react-infinite-scroller

Next is to implement the infinite scroll which will be inside the card components. Navigate to Card component and update the code with the below.

import { useState } from 'react';
import { Card, Button, Container, Col, Row } from 'react-bootstrap'
import InfiniteScroll from 'react-infinite-scroller'; //new
    
export default function CardComponent({ cardData }) {
    const [data, setData] = useState(cardData) //new
       
    const loading = async () => { //new
        const newCardData = [
            {
                title: "New card title",
                buttonName: "right",
                description: "this is an infinite scroll"
            },
            {
                title: "New card title",
                buttonName: "right",
                description: "this is an infinite scroll"
            },
            {
                title: "New card title",
                buttonName: "right",
                description: "this is an infinite scroll"
            }
        ]
        if (data.length <= 20) { //new
            await setData((data) => [...data, ...newCardData])
        }
    }

return (
    <Container>
        <InfiniteScroll //new
            pageStart={0}
            loadMore={loading}
            hasMore={true || false}
            loader={<div className="loader" key={0}>Loading ...</div>}
        >
            <Row>
                {data.map((data, index) => ( //new
                    <Col md={4} key={index}>
                        <Card style={{ width: '18rem' }}>
                            <Card.Img variant="top" src="https://images.unsplash.com/photo-1652512456007-e16ac46f1879?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1100&q=80" />
                            <Card.Body>
                                <Card.Title>{data.title}</Card.Title>
                                 <Card.Text>
                                    {data.description}
                                </Card.Text>
                                <Button variant="primary">{data.buttonName}</Button>
                            </Card.Body>
                        </Card>
                    </Col>
                )
                )}
            </Row>
        </InfiniteScroll>
    </Container>
)
}
Code language: JavaScript (javascript)

Let’s break down this code snippet into chunks.

First, we imported the InfiniteScroll component from react-infinite-scroller. The InfiniteScroll component accepts parameters as follows:

pageStart**={0}** = This accept the page number, mostly when connecting to an API endpoint loadMore**={ }** = This is accept the function that will run when the scroll reaches bottom hasMore**={true || false}** = This accept a boolean value loader**={}** = this allows us to pass a loader.

Next, we set the cardData we passed from our parent component with React useState hook.

Then we have the async loading function that pushes more values to the dataset since we are not using getting data from an API.

Finally, we loop through the cardData and use it in the template.

Save and run the app. You should get something like this:

Infinite scrolling is essential for large datasets cause the user experience is smooth compared to pagination. In this tutorial, we implemented infinite scroll with react-infinite-scroller and lazy loading react components with React.lazy and Suspense.

Happy Coding!

Back to top

Featured Post