Sign in
Log inSign up

How to load more data on scroll using fetch API in React application

Sonu Sasankan's photo
Sonu Sasankan
·Nov 18, 2018

In my react application, I have a list component that fetch some data from an API and display the data. The problem is, I don't want to load all data initially. Instead of this I just want load some limited data first and remaining data on window scroll. How to implement this properly?

Here is my component

import React, { Component } from "react";

import "./PropertyList.css";
import furnished from "../../assets/bed.svg";

class PropertyList extends Component {
  constructor() {
    super();
    this.state = {
      properties: [],
      isLoading: true,
      error: null
    };
  }

  componentDidMount() {

    window.addEventListener('scroll', this.onScroll, false);
    fetch("demo8213882.mockable.io/fetchProperties")
      .then(response => response.json())
      .then(resData => {
        this.setState({
          properties: resData,
          isLoading: false
        });
      })
      // Catch any errors we hit and update the app
      .catch(error => this.setState({ error, isLoading: false }));
  }
  componentWillUnmount() {
    window.removeEventListener('scroll', this.onScroll, false);
  }

  onScroll = () => {
    if (
      (window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 500)) {
      //loadmore data
    }
  }

  render() {
    const { isLoading, properties, error } = this.state;
    return (
      <React.Fragment>
        <div className="row">
          {error ? <p>{error.message}</p> : null}
          {!isLoading ? (
            properties.data.map((item, index) => {
              let images = [];
              let length = item.photos.length;
              console.log(length);
              return (
                <div className="col-md-4 nb-card">
                  <div className="card">
                    <div className="card-body">
                      <h6 className="card-title">{item.title}</h6>
                    </div>
                    <ul className="list-group list-group-flush">
                      <li className="list-group-item">
                        <span>
                          <strong> &#x20b9; {item.rent} Rent</strong>
                        </span>
                      </li>
                      <li className="list-group-item">
                        <span>
                          <strong>{item.propertySize} sqft</strong>
                        </span>
                      </li>
                      <li className="list-group-item">
                        <img className="furnished-icon" src={furnished} />
                        {item.furnishingDesc} Furnished
                      </li>
                    </ul>
                  </div>
                </div>
              );
            })
          ) : (
            // If there is a delay in data, let's let the user know it's loading
            <div className="col-md-8"><p>Loading...</p></div>
          )}
        </div>
      </React.Fragment>
    );
  }
}

export default PropertyList;