gatsby-paginate

by pixelstew

pixelstew / gatsby-paginate

A simple library for paginating posts in Gatsby js.

121 Stars 27 Forks Last release: Not found GNU General Public License v3.0 99 Commits 0 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

Gatsby-paginate

This library provides a simple API for paginating an array of posts/pages for your blog/site homepage in Gatsby js.

LOOKING FOR MAINTAINERS - please email [email protected] with subject GATSBY_PAGINATE

Installation

yarn add gatsby-paginate

Usage

  • Require the package in your
    gatsby-node.js
    file.
  • Add a call to createPaginatedPages in
    gatsby-node.js
    .

Then add the following to the top of your

gatsby-node.js
file.
const createPaginatedPages = require('gatsby-paginate')

Use case 1 - paginate list of posts on home page

To create a paginated index of your blog posts, you need to do four things:

  • Remove the
    index.js
    file from the pages directory.
  • Create an
    index.js
    file in the templates directory and refer to it in the createPaginatedPages call

Call createPaginatedPages

You probably already have something like this in your

gatsby-node.js
file to generate the pages for your blog:
exports.createPages = ({ graphql, actions: { createPage } }) => {
  return new Promise((resolve, reject) => {
    graphql(`
      {
        posts: allMarkdownRemark(
          sort: { fields: [frontmatter___date], order: DESC }
        ) {
          edges {
            node {
              id
              frontmatter {
                title
              }
              fields {
                slug
              }
            }
          }
        }
      }
    `).then(result => {
      result.data.posts.edges.map(({ node }) => {
        createPage({
          path: node.fields.slug,
          component: path.resolve('./src/templates/post.js'),
          context: {
            slug: node.fields.slug,
          },
        })
      })
      resolve()
    })
  })
}

Just insert a call to

createPaginatedPages
before (or after) the createPage function:
exports.createPages = ({ graphql, actions: { createPage } }) => {
  return new Promise((resolve, reject) => {
    graphql(`
      //graphql query
    `).then(result => {
      createPaginatedPages({
        edges: result.data.posts.edges,
        createPage: createPage,
        pageTemplate: 'src/templates/index.js',
        pageLength: 5, // This is optional and defaults to 10 if not used
        pathPrefix: '', // This is optional and defaults to an empty string if not used
        context: {}, // This is optional and defaults to an empty object if not used
      })
      result.data.posts.edges.map(({ node }) => {
        createPage({
          path: node.fields.slug,
          component: path.resolve('./src/templates/post.js'),
          context: {
            slug: node.fields.slug,
          },
        })
      })
      resolve()
    })
  })
}

Notice that

createPaginatedPages
is being passed an options object.
  1. edges
    is the array of nodes that comes from the GraphQL query.
  2. createPage
    is simply the
    createPage
    function you get from
    actions
    .
  3. pageTemplate
    is a template to use for the index page. And
  4. pageLength
    is an optional parameter that defines how many posts to show per index page. It defaults to 10.
  5. pathPrefix
    is an optional parameter for passing the name of a path to add to the path generated in the
    createPage
    func. This is used in use case 2 below.
  6. context
    is an optional parameter which is used as the
    context
    property when
    createPage
    is called.

createPaginatedPages
will then call
createPage
to create an index page for each of the groups of pages. The content that describes the blogs (title, slug, etc) that will go in each page will be passed to the template through
props.pageContext
so you need to make sure that everything that you want on the index page regarding the blogs should be requested in the GraphQL query in
gatsby-node.js
.

Use case 2 - paginate a post or use pagination on a page other than index

Call createPaginatedPages in the same way as above but...

This time pass in a

pathPrefix
createPaginatedPages({
  edges: result.data.posts.edges,
  createPage: createPage,
  pageTemplate: 'src/templates/your_cool_template.js',
  pageLength: 5,
  pathPrefix: 'your_page_name',
  buildPath: (index, pathPrefix) =>
    index > 1 ? `${pathPrefix}/${index}` : `/${pathPrefix}`, // This is optional and this is the default
})

Then...

  • Create a template in tha same way as above but this time
  • Add a
    pathPrefix
  • (optional) add
    buildPath
    if you want to have more control over the pagination URL structure

In this instance a new set of pages will be created at the following path

your_site/your_page_name
Then a second paginated page of
your_site/your_page_name/2

PLEASE NOTE: THE PATH PREFIX FUNCTIONALITY IS UNDER DEVELOPMENT AND MORE FLEXIBILITY WILL BE ADDED SOON

Create the template

This is a simple template which might be used in use case 1 above to replace the index of a blog with a paginated list of posts.

The

pageContext
object which contains the following 5 keys is passed to the template;
  1. group
    - (arr) an array containing the number of edges/nodes specified in the
    pageLength
    option.
  2. index
    - (int) this is the index of the edge/node.
  3. first
    - (bool) Soon to be deprecated - please calculate first using index and pageCount - is this the first page?
  4. last
    - (bool) Soon to be deprecated - please calculate last using index and pageCount - is this the last page?
  5. pageCount
    - (int) the total number of pages being paginated through
  6. additionalContext
    - (obj) optional additional context
import React, { Component } from 'react'
import Link from 'gatsby-link'

const NavLink = props => { if (!props.test) { return {props.text} } else { return {props.text} } }

const IndexPage = ({ pageContext }) => { const { group, index, first, last, pageCount } = pageContext const previousUrl = index - 1 == 1 ? '/' : (index - 1).toString() const nextUrl = (index + 1).toString()

return (

{pageCount} Pages

  {group.map(({ node }) => (
    <div key="{node.id}" classname="blogListing">
      <div classname="date">{node.frontmatter.date}</div>
      <link classname="blogUrl" to="{node.fields.slug}">
        {node.frontmatter.title}

      <div>{node.excerpt}</div>
    </div>
  ))}
  <div classname="previousLink">
    <navlink test="{first}" url="{previousUrl}" text="Go to Previous Page"></navlink>
  </div>
  <div classname="nextLink">
    <navlink test="{last}" url="{nextUrl}" text="Go to Next Page"></navlink>
  </div>
</div>

) } export default IndexPage

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.