Pagination in JavaScript
Pagination means splitting a large collection of data into smaller parts.
Instead of loading everything at once, the server sends only one small group of records.
You will learn:
- what pagination is
- why loading all data at once is a bad idea
- how
_limitworks - how
_pageworks - how to load data in groups
- how the Load more button works
- how to detect the end of the collection
- how to calculate the number of pages
1. What is pagination?
Pagination means loading data in small groups, not all at once.
For example:
- 5 posts at a time
- 10 products at a time
- 20 comments at a time
Pagination = loading data in small groups, not all at once
Big collection
-> split into smaller groups
-> load one group at a time
If a database has thousands of records, it is not practical to load everything in one request.
2. Why avoid loading the whole collection?
If a collection is very large, loading everything at once causes problems.
- The browser must process a lot of data.
- The request takes longer.
- The server must prepare and send a huge response.
- The user usually sees only the first part of the data.
Too much data at once
|
|- browser works harder
|- network is slower
|- server works harder
`- user sees only first part anyway
Pagination solves these problems by sending data in smaller pieces.
3. Example without pagination
Suppose we request all posts:
const fetchPosts = async () => {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts");
console.log("Posts: ", response.data);
};
This gets the whole /posts collection.
Request all posts
-> server sends full collection
-> browser receives everything
That may work for small examples, but in a real application it is often inefficient.
4. Limiting the number of items
The first step of pagination is limiting how many records come back in one response.
Different backends may use different parameter names, for example:
per_pagelimit_limitcount
There is no universal rule. The parameter name depends on the backend.
In JSONPlaceholder, the parameter is _limit.
Collection has many records
-> _limit tells server:
"send only this many"
5. Example with _limit
const fetchPosts = async () => {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts?_limit=5");
console.log("Posts: ", response.data);
};
Here the server does not send all posts. It sends only 5 posts.
_limit=5
= return only 5 records
/posts
-> apply _limit=5
-> only 5 posts are returned
This is the foundation of pagination. First, decide how many items should be in one group.
6. What if _limit is wrong?
If you send a strange value, such as a negative number or a number larger than expected, the server may behave differently depending on its implementation.
It may:
- ignore the value
- use a default value
- return an error like
400 Bad Request
So always use reasonable values.
7. Getting the next group of records
If you only use _limit, you always get the first group.
_limit=5
= first 5 records
But if you want the next 5 records, you need the second pagination parameter: _page.
In other APIs it may be called page.
_limit = how many items
_page = which group of items
Pagination usually needs both the size of the group and the number of the group.
8. Example with _limit and _page
const fetchPosts = async () => {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts?_limit=5&_page=3");
console.log("Posts: ", response.data);
};
Here:
_limit=5means 5 items per group_page=3means the third group
Page 1 - records 1-5
Page 2 - records 6-10
Page 3 - records 11-15
The page number tells the server which group to return.
9. How page groups work
If _limit = 5, the groups look like this:
Page 1 - 1-5
Page 2 - 6-10
Page 3 - 11-15
Page 4 - 16-20
...
Full collection
|
|- Page 1
|- Page 2
|- Page 3
|- Page 4
`- ...
Pagination means moving through the collection group by group.
10. Why _page is useful
Without _page, you always receive the same first records.
With _page, you can move forward through the collection.
_limit controls group size
_page controls group number
11. Backend metadata
Some APIs return extra information together with the data, for example:
- total number of items
- total number of pages
This is useful because the frontend can understand when the collection ends.
If the backend returns total items, you can calculate total pages.
total_pages = total_items / per_page
In practice, it is safer to round up:
Math.ceil(totalItems / perPage)
total items
/
items per page
-> total pages
If the division gives a decimal number, round up because even a partly filled last page still counts as one page.
12. Important correction: use Math.ceil()
If there are 100 posts and 30 posts per page:
Math.ceil(100 / 30)
Result:
4
Because:
- page 1 has 30 records
- page 2 has 30 records
- page 3 has 30 records
- page 4 has 10 records
100 items
/ 30 per page
= 3.33...
-> round up
-> 4 pages
Even though the last page is not full, it still exists.
13. JSONPlaceholder limitation
JSONPlaceholder supports _limit and _page, but it does not give full pagination metadata in the way many real APIs do.
So in this lesson, the end-of-collection logic is implemented on the frontend manually.
That means the frontend developer must decide how many total records exist and calculate the total number of pages.
14. The Load more technique
A common interface pattern is the Load more button.
Instead of showing all posts immediately:
- load the first group
- show them
- when the user clicks again, load the next group
- add it below the existing posts
Click button
-> load page 1
-> show records
Click again
-> load page 2
-> add records below
Click again
-> load page 3
-> add more records
This way the page grows step by step instead of loading everything at once.
15. How the Load more logic works
The usual logic is:
- create a variable
page - set it to
1 - after each successful request, increase
page - use the new value for the next request
let page = 1;
const limit = 5;
Then after a successful request:
page += 1;
Start:
page = 1
After first request:
page = 2
After second request:
page = 3
After third request:
page = 4
The page variable remembers which group should be loaded next.
16. Example of paginated request with variables
let page = 1;
const limit = 5;
const fetchPosts = async () => {
const response = await axios.get("https://jsonplaceholder.typicode.com/posts", {
params: {
_limit: limit,
_page: page,
},
});
console.log(response.data);
page += 1;
};
This version is cleaner because _limit uses a variable, _page uses a variable, and page changes after each request.
17. Adding new records to the page
When the next page is loaded, you usually do not replace the old list.
You append the new records below the old ones.
So the user sees:
- first group
- then second group under it
- then third group under it
First click
-> [posts 1-5]
Second click
-> [posts 1-5]
[posts 6-10]
Third click
-> [posts 1-5]
[posts 6-10]
[posts 11-15]
This is why Load more feels natural.
18. Checking the end of the collection
At some point, there are no more posts to load.
So before making a new request, the app should check whether more pages still exist.
If not, it should show a message like:
We're sorry, there are no more posts to load
This improves UX because the user understands that loading is finished.
Current page > total pages?
|- yes -> show message
`- no -> send next request
19. Calculating total pages
let limit = 30;
const totalPages = Math.ceil(100 / limit);
Here:
100is the total number of posts30is posts per page
Result:
4
limit = 30
total items = 100
100 / 30 = 3.33...
Math.ceil(3.33...) = 4
So there are 4 pages total.
20. Check before sending the next request
Before the next request, compare the current page with totalPages.
if (page > totalPages) {
return iziToast.error({
position: "topRight",
message: "We're sorry, there are no more posts to load"
});
}
If page is already bigger than totalPages, then all records are already loaded.
Before request
-> Is page > totalPages?
|- yes -> stop and show message
`- no -> continue request
21. Why this check is useful
This check gives two benefits:
- It avoids useless requests because there is no need to ask the server for data that does not exist.
- It improves user experience because the user gets clear feedback that the collection is finished.
End check
|
|- avoids unnecessary server requests
`- improves UX
22. Full pagination idea in one view
Pagination usually works like this:
- choose
limit - start with
page = 1 - request records with
_limitand_page - render them
- increase
page - stop when all pages are loaded
Set limit
-> Set page = 1
-> Request page 1
-> Render posts
-> Increase page
-> Request next page
-> Repeat until page > totalPages
23. Common beginner mistakes
- Loading the whole collection immediately.
- Using only
_limit, which loads the first group again. - Forgetting to increase
page. - Using normal division without rounding up.
- Sending requests after the collection has ended.
const totalPages = 100 / 30;
Better:
const totalPages = Math.ceil(100 / 30);
Need pagination?
-> Use limit
-> Use page
-> Increase page after success
-> Use Math.ceil for total pages
-> Check collection end before next request
24. Easy memory rules
Pagination = load data in groups
_limit = how many items
_page = which group
page += 1 = move to next group
Math.ceil(totalItems / limit) = total pages
if page > totalPages = stop loading
25. Quick summary
- Pagination means splitting a large collection into smaller groups.
- It improves performance and user experience.
_limitcontrols how many items are returned._pagecontrols which group of items is returned._limit=5&_page=3means return 5 items from the third group.- The Load more technique uses a
pagevariable that increases after each request. - The total number of pages is usually calculated with
Math.ceil(totalItems / limit). - Before sending a new request, check whether there are more pages to load.
26. Final conclusion
If you understand these ideas, you already have a strong foundation for using pagination in JavaScript:
pagination
_limit
_page
page variable
Load more
totalPages
Math.ceil
end of collection
Pagination is very important in real applications because large collections are everywhere: posts, products, comments, users, and search results.