yung peso
yung peso

Reputation: 1766

React - How can I get pagination to re-render based off amount of objects per view selected via user-input?

I have a pagination that works with <ToggleButtons> ,users can select how many items they want to display per page. The problem is, when a user select's a different amount of items to display other than the default, the pagination display shows more than needed page numbers because the calculation of items to display doesn't get re-calculated into the <Pagination> function. So the interface is still displaying the default number of page numbers.

Please see this sandbox for more info:

https://codesandbox.io/s/wizardly-agnesi-29zq8?file=/src/App.js

Basically I have these buttons that display 2, 4, or 6 items. If you toggle any of the buttons you will see that the pagination UI does not re-render itself to calculate the correct number of pages. In return there are useless pages in the interface that do nothing. Please see for yourself in the link above.

How can I solve for this? I've tried adding another state but I still had the same problem.

Upvotes: 0

Views: 1812

Answers (2)

kev_cudi
kev_cudi

Reputation: 86

The answer is that you need to make sure that you are updating the noOfPages when itemsPerPage changes . Take a look at this example:

https://codesandbox.io/s/hardcore-smoke-dsxqo?file=/src/App.js

I have only made a few changes to your setup, but you can see that it should solve your problems. This function here is doing all of the heavy lifting.

  const handleItemsPerPage = (event, newAmount) => {
    if (newAmount === null) {
      setItemsPerPage(5);
      setNoOfPages(Math.ceil(SymbolData.length / 5));
      return null;
    }

    setItemsPerPage(newAmount);
    setNoOfPages(Math.ceil(SymbolData.length / newAmount));

    // Checking if the page number is too high given # per page.
    if (page > Math.ceil(SymbolData.length / newAmount)) {
      setPage(Math.ceil(SymbolData.length / newAmount));
    }
  };

For starters I added the null check before attempting to set state. Then I just updated the number of pages (setNoOfPages) to account for the new change in display number per page.

Finally I added one check that will help with your UX. If the user is viewing 2 results per page, then there are 5 pages. However, if they switch the number of results per page to 6, then there are only 2 pages, but the selected page is still 5. So I added a check to determine whether or not your app should update the current page to be within the range of total pages.

I realize that you didn't ask for that, but it was bugging me so I threw it in. Ideally you might even want to handle some of this with useEffect, but since that isn't part of your current code I didn't want to add complexity.

Upvotes: 1

Jayce444
Jayce444

Reputation: 9063

You need to re-calculate the number of pages when the items per page changes. You can do this with an effect, so import it and then add this inside your component:

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

...


useEffect(() => {
     setNoOfPages(Math.ceil(SymbolData.length / itemsPerPage));
}, [itemsPerPage]);

Of course setNoOfPages is the setter for the number of pages state, so gotta destructure that too when defining the state:

const [noOfPages, setNoOfPages] = React.useState(
    Math.ceil(SymbolData.length / itemsPerPage)
);

I tweaked your sandbox to show this here

Upvotes: 1

Related Questions