Static pagination in NextJS

Viewed 10578

I'm trying to set up pagination in Next JS, but I'm not able to figure out how to achieve this through getStaticProps. I am able to do this through getServerSideProps with the query parameter, but this is not accessible through getStaticProps. The data is coming from local Strapi backend.

Here is the example of getServerSideProps (which works):

export async function getServerSideProps({ query: { page = 1 } }) {
const { API_URL } = process.env;

const start = +page === 1 ? 0 : (+page - 1) * 3;
const numberOfCakesRes = await fetch(`${API_URL}/cakes/count`);
const numberofCakes = await numberOfCakesRes.json();

const res = await fetch(`${API_URL}/cakes?_limit=3&_start=${start}`);
const data = await res.json();

return {
    props: {
        cakes: data,
        page: +page,
        numberofCakes,
    },
};

}

Then I just hook up the buttons to the router to go back and forth.

onClick={() => router.push(`/?page=${page - 1}`)}

I need access to something similar to the query parameter in getServerSideProps. Is what I'm asking for achievable statically?

2 Answers

Because getStaticProps runs at build time, it does not receive data that’s only available during request time, such as query parameters or HTTP headers as it generates static HTML. docs

One thing you can do is instead of putting the page no in the query, put it as a route parameter, i.e users will visit /3 instead of /?page=3.

To achieve it, you need to create a [page].js in the pages directory and export a getStaticPaths function:

export async function getStaticPaths() {
  // query Strapi to calculate the total page number
  return {
    paths: [
      { params: { page: '1' } },
      { params: { page: '2' } },
      { params: { page: '3' } }
    ],
    fallback: true or false // See the "fallback" section in docs
  };
}

And also a getStaticProps function:

export async function getStaticProps(context) {
  const { page } = context.params;
  // fetch page data 
  return {
    props: { ... }, 
  }
}

Learn more about getStaticPaths and getStaticProps in Next.js docs.

If you really want to use the query parameters for your pagination (sth like /foo?page=2) and SSG together, there is a workaround I just came up with.

You can use Next JS rewrites and redirects features.

First, use the /foo/[page].js file format and statically generate all the pages, as hangindev.com has explained.

Then, in the next.config.js file, you have to export two functions:
async redirects() and async rewrites().

module.exports = {
  ....
  async redirects() {
    return [
      {
        source: "/foo/1",
        destination: "/foo?page=1",
        permanent: true,
      },
      {
        source: "/foo/2",
        destination: "/foo?page=2",
        permanent: true,
      },
      {
        source: "/foo/3",
        destination: "/foo?page=3",
        permanent: true,
      },
    ];
  },

  async rewrites() {
    return [
      {
        source: "/foo",
        has: [{ type: "query", key: "page", value: "1" }],
        destination: "/foo/1",
      },
      {
        source: "/foo",
        has: [{ type: "query", key: "page", value: "2" }],
        destination: "/foo/2",
      },
      {
        source: "/foo",
        has: [{ type: "query", key: "page", value: "3" }],
        destination: "/foo/3",
      },
    ];
  },
  
};

The redirects() function, ensures that users can't see the pages in /foo/2 format, because they get redirected to /foo?page=2. And the rewrites() function displays the content from /foo/2 page for the /foo?page=2 URL.

Related