Implement pagination for API calls within a React Component

I am trying to implement pagination for the results of an API call. The following code snippet shows how I am making the API call using Axios:

apiCall() {
const API = `http://www.omdbapi.com/`;
axios.get(API, {
        params: {
            apikey: process.env.REACT_APP_MOVIECALL_API_KEY,
            type: 'movie',
            s: 'superhero',
            page: this.state.pageCount
        }
    })
    .then(res => {
        const superheroes = res.data.Search
        const totalResults= parseInt(res.data.totalResults)
        this.setState({
            totalResults
        });
        this.setState({
            superheroes
        })
    })
    .catch((error) => {
        console.log(error);
    });
}

The function is called when the component is mounted as follows:

componentDidMount() 
{ 
  this.apiCall();
}

In the render function, each search result is mapped over (the 's' param in the API call is the search option), and a button is displayed for each result. Clicking on the button displays related information about that movie. By default, the API displays 10 results per call, but this particular search has a total of 123 results. Currently, the page number is hardcoded inside the state to show the corresponding list of 10 movies.

I want to paginate the results by updating the page number so that clicking on 'next' or page numbers like 3/4/5 loads the correct results. I've tried some options related to React but they haven't updated the page number correctly.

If anyone has a simpler and more elegant solution for implementing pagination in this specific scenario, I would appreciate any guidance.

Below is the complete component code for reference:

The existing implementation seems to work fine. I'm looking for a more streamlined approach to pagination for this use case.

export class MovieDetails extends Component {
  constructor(props){
    super(props)
    this.state = {
      superheroes: [],
      clicked: false,
      activeHero: {},
      pageCount: 11,
      totalResults: null,
      currentPage: 1
    }
    this.handleClick = this.handleClick.bind(this);
  }


  handleClick(hero) {
    const checkActive = this.state.activeHero.imdbID === hero.imdbID
    const activeHero = {...hero, active: !checkActive}
    this.setState({
      clicked: !this.state.clicked,
      activeHero
    })
  }    

  apiCall() {
    const API = `http://www.omdbapi.com/`;
    axios.get(API, {
            params: {
                apikey: process.env.REACT_APP_MOVIECALL_API_KEY,
                type: 'movie',
                s: 'superhero',
                page: this.state.pageCount
            }
        })
        .then(res => {
            const superheroes = res.data.Search
            const totalResults = parseInt(res.data.totalResults)
            this.setState({
              totalResults
            });
            this.setState({
                superheroes
            })
        })
        .catch((error) => {
            console.log(error);
        });
  }

  componentDidMount() {
    this.apiCall();
    }

    handlePageChange = (page, e) => {
      this.setState({
        currentPage: page
      });
      this.apiCall(this.setState({pageCount: page}))

    };


  render() {

    const {superheroes, currentPage } = this.state
    return (
        <div>
      {
        superheroes.map((hero, i) => 
            <div className="Results" key={i}>
            <button onClick={() => {this.handleClick(hero)}}> 
            <h1>{hero.Title}</h1>
            {
              this.state.clicked && this.state.activeHero.imdbID === hero.imdbID
                ? <ul>
                    {<div key={i}>
                    Movie Title: <h2> {hero.Title}</h2>
                      Year of Release: <h2>{hero.Year}</h2>
                      ID: <h2>{hero.imdbID}</h2>
                      <div><img className="Poster" alt="movieposter" src={hero.Poster}/></div>
                      </div>
              }
            </ul>
          : null
      }
      </button>
      </div>) 
   }
          <div className="Pagination"> 
          <Pagination
          total={this.state.totalResults}
          limit={10}
          pageCount={this.state.pageCount}
          currentPage={currentPage}
        >
          {({
            pages,
            currentPage,
            hasNextPage,
            hasPreviousPage,
            previousPage,
            nextPage,
            totalPages,
            getPageItemProps
          }) => (
            <div>
              <button
                {...getPageItemProps({
                  pageValue: 1,
                  onPageChange: this.handlePageChange
                })}
              >
                first
              </button>

              {hasPreviousPage && (
                <button
                  {...getPageItemProps({
                    pageValue: previousPage,
                    onPageChange: this.handlePageChange
                  })}
                >
                  {'<'}
                </button>
              )}

              {pages.map(page => {
                let activePage = null;
                if (currentPage === page) {
                  activePage = { backgroundColor: '#fdce09' };
                }
                return (
                  <button
                    {...getPageItemProps({
                      pageValue: page,
                      key: page,
                      style: activePage,
                      onPageChange: this.handlePageChange
                    })}
                  >
                    {page}
                  </button>
                );
              })}

              {hasNextPage && (
                <button
                  {...getPageItemProps({
                    pageValue: nextPage,
                    onPageChange: this.handlePageChange
                  })}
                >
                  {'>'}
                </button>
              )}

              <button
                {...getPageItemProps({
                  pageValue: totalPages,
                  onPageChange: this.handlePageChange
                })}
              >
                last
              </button>
            </div>
          )}
        </Pagination>
          </div>
      </div>

    );
  }
}

Answer №1

Within your axios.get call, you are passing page: this.state.pageCount. However, in your handlePageChange function, you are updating this.state.currentPage, which seems incorrect.

I'm also a bit puzzled by the onPageChange event on the <button />. Is this button a custom component that you have imported (if so, it should be capitalized for clarity) or is it a standard HTML button? If it's an HTML button, make sure to use the onClick event handler, which will pass the event as an argument to the handlePageChange function. Based on the props being passed, I believe it is a custom component, but it's still worth verifying whether the page value is being sent correctly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error encountered in AngularJS when utilizing the Flickr API with the parameter "nojsoncallback=1": Unexpected token Syntax

My AngularJS application is trying to access the Flickr API. I need the data in RAW JSON format without any function wrapper, following the guidelines provided in the documentation by using &nojsoncallback=1. However, I keep encountering a console er ...

What is the reason for Next.js and Gatsby.js necessitating the installation of Node.js, while React.js does not have that requirement?

Have you ever thought about the connection between Next.js and Gatsby.js, both being built on React.js? Could it be that the development environments are Node applications themselves? Or maybe there's something else I'm not seeing? While I have ...

Sending pictures to Express via Multer using fetch

I am currently working on uploading images to an Express server. While I have been referencing MDN, express, react-dropzone, and multer Documentation, I am still unsure of the exact process. It seems that Multer is not recognizing the FormData object from ...

What is the reason for the getter not being able to retrieve the value

I am experiencing an issue with a getter that returns an array of objects. The challenge I face is that I need to display past and current warnings in separate components. The getter currently only retrieves the current warning and ignores any past warnin ...

Content retrieved from the getStaticProps function is not appearing on the page component

Recently, I have delved into the world of Next.js and decided to explore the capabilities of getStaticPaths and getStaticProps in conjunction with firebase for my details page. import firebase from '../../firebase' export const getStaticPaths = ...

React Express application malfunctioning when running in production environment

I have successfully developed a Create React App in both development mode using yarn start and yarn build > serve -s build. However, when I try to upload the build folder to my remote server (on Planet Hoster), I encounter the following errors : GET ht ...

Getting an UnhandledPromiseRejectionWarning while attempting to navigate through Google Maps using Node.js Puppeteer

(node:15348) UnhandledPromiseRejectionWarning: Error: Execution context was destroyed due to a potential navigation issue. const browser = await puppeteer.launch({headless: false}); const page = await browser.newPage(); page.goto("https://www.google. ...

Is the Okta SDK compatible with all identity providers?

I am looking to incorporate a wide range of Identity providers into my app, such as Auth0 SSO OIDC, Onelogin SSO OIDC, Google SSO OIDC, and others. Is it possible to use this solution to make that happen? https://github.com/okta/okta-auth-js ...

The cartItems app was unable to find any matching routes for the specified location

Encountering a routing issue while using react-router-dom v6 to manage the functionality of "cart items" in my application. Strangely, the cart items fail to show up when clicking on the "cart" link on the navbar header. However, it functions correctly and ...

Unexplainable space or padding issue detected in OwlCarousel grid gallery

There seems to be an unusual gap or margin at the bottom of each row section in this portfolio grid gallery that's running in OwlCarousel. You can view an example here. https://i.stack.imgur.com/NHOBd.png I've spent a lot of time trying to solv ...

Guide on dynamically adding images in React.js based on their filenames

Currently, I am in the process of implementing a language selection feature and I need to incorporate flags. Initially, I attempted to use Unicode emojis for flags, but unfortunately, they did not display properly when retrieved from React variables. As a ...

Activating Unsplash API to initiate download

I am currently following the triggering guidelines found in the Unsplash documentation. The endpoint I am focusing on is: GET /photos/:id/download This is an example response for the photo: { "id": "LBI7cgq3pbM", "width": ...

Exploring the capabilities of Angular and UIGrid for fetching table information

I have been utilizing Angular along with uigrid, which is an excellent library for displaying data in a tabular format. Everything looks good when displaying the table. However, when I update an item and click on a Save button that triggers a rest service ...

Guide on creating a menu that remains open continuously through mouse hovering until the user chooses an option from the menu

I have a unique scenario where I am working with two images. When the mouse hovers over each image, two corresponding menu bars appear. However, the issue is that when the mouse moves away from the images, the menu disappears. Any suggestions on how to im ...

Adjust the width of MUI DataGrid columns to fit the longest data in each column

When utilizing the DataGrid component from MUI, I have not specified a width in the GridColDef. I am looking to have the columns adjust their width based on the length of the longest data to ensure every letter is fully displayed. Is this achievable? Here ...

html scroll to the flickering page

Why is it that when a user clicks on a link in the list, the browser flickers? This issue becomes especially noticeable if a user clicks on the same 'link' twice. Is there a solution to prevent this from occurring? The problem also seems to aris ...

Tips for managing the onloadedmetadata event

If a video file cannot be played by the browser due to format or codec issues, I want to notify the user about it. When the browser is unable to play a video (because of unsupported format or codec), the onloadedmetadata event does not occur. I have some ...

Transforming with Babel to create pure vanilla JavaScript

Our current development process involves working with a custom PHP MVC Framework that combines HTML (Views), PHP files, and included JS with script tags (including JQuery, Bootstrap, and some old-fashioned JS libs). During the development stages, we want ...

What steps should I take to fix the issue of "[ERR_REQUIRE_ESM]: Must use import to load ES Module" while working with D3.js version 7.0.0 and Next.js version 11.0.1?

Encountered a roadblock while integrating D3 with Next.js - facing an error when using D3.js v7.0.0 with Next.js v11.0.1: [ERR_REQUIRE_ESM]: Must use import to load ES Module Tried utilizing next-transpile-modules without success Managed to make D3.js ...

Retrieving fresh CSS data from earlier animated elements within a Greensock timeline

In my code, I am using a TimelineLite() to perform a series of sequential tweens with .to(). What I want to achieve is accessing the output value from one of the early tweens in order to use it for constructing later tweens. Is there any way to retrieve t ...