Implement pagination with NextJS and MongoDB
If you read my blog regularly you may have noticed that I recently introduced pagination to my article list. In order of that I would like to explain how I implemented that with the tech stack of my blog - NextJS and MongoDB.
Pagination is one of the major mechanisms to reduce the page loading time and is widely adopted. It is a good practice to do pagination when you have many rows, resp. an unknown amount of rows. It can help to improve the performance with three aspects:
- It reduces the query time on the database
- It reduces the payload size returned to the client
- It reduces the amount of elements the browser needs to render
Especially the third point can help a lot when there are some expensive elements such as images per data row.
How does pagination generally work
The mechanism is actually quite simple. The data in its whole needs to be split into junks of the same size. These junks we call pages.
Every page has a
page number, a
size and an
offset. In order to get a reliable result the data needs to be sorted.
We now can translate this into a database query. Usually the databases don't know the concept or pages. But they have a syntax to
take a certain amount of rows. In terms of SQL it would be
fetch. We can translate the page number into this syntax. Assuming the pages starts with
1 we can do following query
skip = (page - 1) * size, take = size.
A full SQL query loading page 2 could look like this:
SELECT * FROM [Posts] ORDER BY [Published] OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
If we know the total amount of rows, we can calculate the total page count as well
Math.Ceil(totalRowCount / size).
Implementing pagination with NextJS server side rendering
Since I have a database, concrete MongoDB, for storing my articles in place I need to use the SSR mechanism of NextJS to pre-render the articles on the server side.
Assuming I have a UI which is illustrated in the next image. It contains a table of data and controls for navigating through the pages. In my case I allow only a navigation forward and backwards. In some implementations there are controls to a dedicated page. But at the end, this does not matter.
Having the designed in place we need a way to tell the server side rendering which page to load. We do that by passing it with the URL as a query parameter