How to Add Pagination to your Gatsby JS Website using gatsby-awesome-pagination

Written by Brian

Today, I will show you how you can add pagination to your Gatsby JS website using an awesome plugin called gatsby-awesome-pagination. You can see the original docs for this plugin here.

The first thing you will need to do is install the gatsby-awesome-pagination plugin. You can use yarn or npm to install it. I have yarn, so I will use the code below.

yarn add gatsby-awesome-pagination

Next, you will need to import paginate into your gatsby-node.js file

import { paginate } from "gatsby-awesome-pagination"

Then, you will have to add the paginate method and update the values.

The docs have a template that you can fill out, but I'll show you how I did mine, in case you were confused with the way they did it.

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query {
      allMdx(filter: { fileAbsolutePath: { regex: "/posts/" } }) {
        edges {
          node {
            frontmatter {
              slug
            }
          }
        }
      }
    }
  `)

  paginate({
    createPage, // The Gatsby `createPage` function
    items: result.data.allMdx.edges, // An array of objects
    itemsPerPage: 6, // How many items you want per page
    pathPrefix: "/posts", // Creates pages like `/blog`, `/blog/2`, etc
    component: path.resolve("src/templates/blog.js"), // Just like `createPage()`
  })
}

So, my setup is a little different from the official docs. Basically, I query the data from graphql to display all my MDX files. I have multiple folders with different types of content, but I only want to use the pagination for my posts folder.

If you only have one folder for your content, then you can ignore the filter I put. However, if you need to filter for a specific type of content, then you would want to add this code into your graphql query.

filter: {
  fileAbsolutePath: {
    regex: "/posts/"
  }
}

Again, this is completely optional, but I couldn't find any tutorials showing that option, so I figured I'd leave that in.

So, looking at the paginate method, you simply just have to add your values into the object.

paginate({
  createPage, // The Gatsby `createPage` function
  items: result.data.allMdx.edges, // An array of objects
  itemsPerPage: 6, // How many items you want per page
  pathPrefix: "/posts", // Creates pages like `/blog`, `/blog/2`, etc
  component: path.resolve("src/templates/blog.js"), // Just like `createPage()`
})

I set my items per page to only show 6 posts. The pathPrefix is what you want your URL to be when showing the pagination.

I want to display my blog post on the "/posts" URL, so I set it as "/posts" for the pathPrefix. The last value is for the component and you will need to create one (if you don't have one already) to display your post.

First, create a new file in your templates folder. I called mine blog.js.

Here is an example of my code for the blog.js file. Note, whatever you name your file is what you put for the components value in the pagination method.

Here you can see that I have my template located in my templates folder with the file name of blog.js.

component: path.resolve("src/templates/blog.js")

Next, you can add your code to the blog.js file.

const Blog = ({ data, pageContext }) => {
  const {
    allMdx: { nodes: posts },
  } = data
  return (
    <Layout>
      <SEO title="Posts" />
      <h1 className="post__heading">Check out my Blog Post</h1>
      <Posts posts={posts} key={posts.id} />
      <Pager pageContext={pageContext} />
    </Layout>
  )
}

export default Blog

Blog.propTypes = {
  data: PropTypes.object.isRequired,
  pageContext: PropTypes.object.isRequired,
}

export const query = graphql`
  query($skip: Int!, $limit: Int!) {
    allMdx(
      filter: { fileAbsolutePath: { regex: "/posts/" } }
      sort: { order: DESC, fields: frontmatter___date }
      skip: $skip
      limit: $limit
    ) {
      nodes {
        id
        frontmatter {
          title
          path
          slug
          date(formatString: "MMMM Do, YYYY")
          image {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
  }
`

I have a separate component called Posts that maps through all my posts and displays them. You would replace that with your own component that displays your content.

<Posts posts={posts} key={posts.id} />

Then, you would just query the data from graphql. Yours will most likely look different from mine.

The final thing you need to do is create a pager.js file that will display the pagination.

I created mine in my components folder.

Here is an example of the code I used for my pager.js file. You will have to customize the CSS to fit your own design.

const Pager = ({ pageContext }) => {
  const {
    previousPagePath,
    nextPagePath,
    humanPageNumber,
    numberOfPages,
  } = pageContext

  return (
    <div className="pager">
      <nav className="pager__container">
        {previousPagePath ? (
          <Link to={previousPagePath} className="pager__button">
            <button>
              <FiArrowLeft className="pager__icon--left" />
              Previous Page
            </button>
          </Link>
        ) : null}
        {numberOfPages > 1 && (
          <div className="pager__location">
            Page {humanPageNumber} of {numberOfPages}
          </div>
        )}
        {nextPagePath && (
          <Link to={nextPagePath} className="pager__button">
            <button>
              See More Posts
              <FiArrowRight className="pager__icon--right" />
            </button>
          </Link>
        )}
      </nav>
    </div>
  )
}

Pager.propTypes = {
  pageContext: PropTypes.object.isRequired,
}

export default Pager

This code below is optional, but it displays the total number of pages based off your content. If you have 12 blog posts and display 6 posts per page, then it will say page 1 of 2.

{
  numberOfPages > 1 && (
    <div className="pager__location">
      Page {humanPageNumber} of {numberOfPages}
    </div>
  )
}

The rest of the code just shows the previous and next button options.

Once you completed all those steps, restart your server and you will see the pagination displaying on your website.

If you run into any issues, feel free to send me a message!

Also, I'm documenting everything I'm learning and the projects I'm building on my Youtube channel. If you want to follow me along my coding journey, be sure to subscribe here