Implement pagination with NextJS and MongoDB

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 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:

  1. It reduces the query time on the database

  2. It reduces the payload size returned to the client

  3. 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 as a whole needs to be split into junks of the same size. These junks we call pages.

Row junks|469x155

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 skip and take a certain amount of rows. In terms of SQL, it would be offset and fetch. We can translate the page number into this syntax. Assuming the pages start 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 navigation forward and backwards. In some implementations, there are controls for a dedicated page. But in the end, this does not matter.

Pagination UI|253x169

Having the design 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 https://domain/blog?page=2.