Reputation: 19
I am building a simple app that calls 100 users from an API and displays them in a grid. I have filters for gender and an input for username search. I also added pagination to display 20 users per page. I pass props for the currentData and pagination functions to the child component (Feed)
My issue is: when I search the username in input, the pagination holds strong and it gives the impression there are no matching users, however when you navigate to pages 4 or 5 they will appear if they exist there.
Relevant code here:
App.js
//
const [currentPage, setCurrentPage] = useState(1);
const [usersPerPage, setUsersPerPage] = useState(20);
const paginate = (number) => setCurrentPage(number);
const lastUserIndex = currentPage * usersPerPage;
const firstUserIndex = lastUserIndex - usersPerPage;
const currentData = data?.slice(firstUserIndex, lastUserIndex);
Feed.js
//
if (username.length >= 1) {
setUsersPerPage(100)
} else {
setUsersPerPage(20)}
My initial thought (above) was to set all the users on one page to ensure the username filter picks up all the users in my data and display them on the one page. However a warning is being thrown in the console (the same as this https://github.com/facebook/react/issues/18178#issuecomment-595846312) as when the page first loads, it simultaneously sets the usersPerPage in both App.js and Feed.js. I tried migrating all the pagination functionality to Feed.js, but there was an issue with passing the props.
Any help or logic to figure this out would be much appreciated!
Upvotes: 0
Views: 1302
Reputation: 330
Based on the sandbox you linked in the comments I would say you need to rethink your component flow.
There doesn't seem to be a need to call your API in the App Component. Instead call that in your Feed component. That will make things easier to follow and separate your concerns.
The other issue I see is that your pagination component is coupled to the amount of total users, not the amount of users you are displaying in the Feed component.
Your pagination component should be dynamic and based on the amount of users you want to display in total. The logic to paginate should see that you are trying to display more than your page limit (i.e 25) and create new pages.
You could do this in several ways, but a simple one that comes to mind is to create a state array of 'pages', and have a function that updates the pages state with nested arrays of less than 25 elements.
Then you can have something like so:
const [pages, setPages] = [];
const pageLimit = 25;
const updatePages = (users) => {
let nPages = [];
// break up user array into chunks of page limits
for (let i = 0; i < users.length; i+= pageLimit) {
nPages.push(users.slice(i, i + pageLimit))
}
setPages(nPages);
}
Now you have an array of all the pages you need to display. So when you add a filter and call updatePages
with only a single user, your components can know there is only a single page to display, with only a single user on that page.
This is just an example of how you might rethink this issue. But the key take away is that you need to couple your pagination to what is being rendered instead of how many items were retrieved from your initial API call.
Upvotes: 1