DEV Community

Abhay Singh Kathayat
Abhay Singh Kathayat

Posted on

Mastering Paginated API Calls in React for Optimized Data Fetching

Paginated API Calls in React

Paginated API calls are a method used to fetch data in chunks rather than loading everything at once. This is especially useful when dealing with large datasets that could otherwise overwhelm both the client and server. Pagination is a standard technique in web development where the data is divided into pages, and the user can navigate through them to view more data. In a React application, paginated API calls allow efficient data fetching by requesting only a small portion of the dataset at a time, improving performance and user experience.


1. Why Use Paginated API Calls?

  • Performance: Loading large datasets in small chunks prevents your app from freezing or becoming unresponsive.
  • Server Load: By requesting smaller portions of data, you reduce the load on the server and improve response times.
  • User Experience: Users can start interacting with the data right away, rather than waiting for the entire dataset to load.

2. How Paginated API Calls Work

Paginated API calls typically return data in chunks. For example, an API might return 10 items per page and provide metadata about the total number of items or available pages. The client app can use this information to manage the current page and trigger additional requests when needed.

Common API response structure for pagination:

{
  "data": [
    // Array of items
  ],
  "total": 100,  // Total number of items
  "page": 1,     // Current page number
  "per_page": 10 // Items per page
}
Enter fullscreen mode Exit fullscreen mode

3. How to Implement Paginated API Calls in React

Let’s look at an example of implementing paginated API calls in React using the useState and useEffect hooks.

Step 1: Setting up the Component

import React, { useState, useEffect } from 'react';

const PaginatedAPI = () => {
  const [data, setData] = useState([]);          // Store fetched data
  const [loading, setLoading] = useState(false);  // Track loading state
  const [currentPage, setCurrentPage] = useState(1); // Current page number
  const [hasMore, setHasMore] = useState(true);   // Check if there is more data to fetch

  const itemsPerPage = 10; // Number of items per page

  // Fetch paginated data from API
  const fetchData = async (page) => {
    if (loading) return; // Prevent making multiple requests at the same time

    setLoading(true);

    try {
      // Replace with your actual API endpoint
      const response = await fetch(`https://api.example.com/items?page=${page}&limit=${itemsPerPage}`);
      const result = await response.json();

      setData((prevData) => [...prevData, ...result.data]); // Append the new data to the current list

      // Check if there are more pages to load
      if (result.data.length < itemsPerPage) {
        setHasMore(false); // No more data to fetch
      }
    } catch (error) {
      console.error("Error fetching data:", error);
    } finally {
      setLoading(false);
    }
  };

  // Trigger fetch on page load and when the page changes
  useEffect(() => {
    fetchData(currentPage);
  }, [currentPage]);

  // Load more items when the user reaches the bottom of the list
  const handleLoadMore = () => {
    if (!loading && hasMore) {
      setCurrentPage((prevPage) => prevPage + 1);
    }
  };

  return (
    <div>
      <h1>Paginated Data</h1>
      <div>
        {data.map((item, index) => (
          <div key={index}>{item.name}</div> // Assuming each item has a 'name' field
        ))}
      </div>

      {loading && <div>Loading...</div>}

      {!loading && hasMore && (
        <button onClick={handleLoadMore}>Load More</button>
      )}

      {!hasMore && <div>No more data to load</div>}
    </div>
  );
};

export default PaginatedAPI;
Enter fullscreen mode Exit fullscreen mode

4. Explanation of Code

State Management:

  • data: Stores the items fetched from the API.
  • loading: Tracks whether a fetch request is in progress.
  • currentPage: The current page number, used to determine which page of data to fetch.
  • hasMore: A boolean value that determines if there are more pages of data to load.

fetchData Function:

This function is responsible for fetching the data from the API. It uses the page and limit query parameters to fetch a specific page of data. Once the data is fetched, it is appended to the existing list of items.

handleLoadMore Function:

This function is called when the user clicks the "Load More" button. It increments the currentPage by 1 and triggers a new fetch request to load more data.

useEffect:

  • This hook fetches the data for the current page when the component mounts or when the page number changes (currentPage dependency).

Rendering:

  • The fetched data is displayed in a list, with a "Load More" button that appears when more data can be loaded.
  • A loading spinner is shown while the data is being fetched.
  • If there are no more items to load (hasMore is false), a message is displayed.

5. Advantages of Paginated API Calls

  • Performance: Reduces the initial load time and improves performance by fetching only the necessary data.
  • Better Resource Usage: Fetching data in chunks minimizes memory usage and reduces the number of server requests.
  • Scalable: Allows the application to scale as more data becomes available by simply adjusting the pagination logic.

6. Optimizing Paginated API Calls

  • Debouncing User Actions: In some cases, you may want to debounce the user’s scroll or clicks to avoid excessive API calls.
  • Caching: Use caching techniques (e.g., React Query, SWR) to store and reuse previously fetched data, reducing the number of redundant API calls.
  • Prefetching: In some cases, you can prefetch the next page of data in advance to make the transition between pages smoother.

7. Using External Libraries for Pagination

For more complex pagination, consider using libraries like:


8. Conclusion

Paginated API calls are an essential technique for handling large datasets in React apps. By requesting data in smaller chunks, you can improve performance, reduce server load, and enhance the user experience. Whether you're fetching data on scroll or using pagination controls, React provides the flexibility to implement paginated calls efficiently using hooks like useState and useEffect.


Top comments (0)