DEV Community

Praveen Bisht
Praveen Bisht

Posted on • Edited on • Originally published at prvnbist.com

Link prev/next articles dynamically on your gatsby blog

Introduction

Linking your next and previous article doesn't require any packages to be installed, infact it's quite simple to implement.

Alt Text

If you have an up and running blog with articles then you must have used Gatsby's createPages api. This api provides a createPage function that takes an object as it's first argument, gatsby refers to this object as page object. This page object takes following key's.

  • path : a path url where your articles will be available to read from.
  • component : a path to the react component that'll render the content of the article usually referred to as article template.
  • context : an object using which you can pass any key-value that you would want to read from the article template.

We'll be using the context key to implement this functionality.

Let's code

Each article rendered using article template get's a list of props from the createPage function. It contains a prop named pageContext. Any key-value, we define inside the context will be available through this pageContext prop. We'll be passing two keys named: prev and next representing details of previous and next article respectively.

Getting details of next/previous articles

In order to get list of all articles, we use a GraphQL query. Something like -

const result = await graphql(`
   query {

      // if you're using just markdown, replace allMdx with allMarkdownRemark
      allMdx(sort: { order: DESC, fields: [frontmatter___date] }) {
         edges {
            node {
               fields {
                  slug
               }
               frontmatter {
                  title
               }
            }
         }
      }
   }
`)
Enter fullscreen mode Exit fullscreen mode

This essentially returns all the articles, in the query above, the field edges represent list of all the articles and the field node represent each article. Let's assign the edges to a variable.

const articles = result.data.allMdx.edges
Enter fullscreen mode Exit fullscreen mode

Now to get the next and previous article we can just use articles[index-1].node for previous article and articles[index+1].node for next article. And incase if it's the first article, previous would be null and for the last article next would be null.

For previous article

articles.forEach(({ node }, index) => {
   createPage({
      ...
      context: {
         ...
         prev: index === 0 ? null : articles[index - 1].node
      }
   })
})
Enter fullscreen mode Exit fullscreen mode

For next article

articles.forEach(({ node }, index) => {
   createPage({
      ...
      context: {
         ...
         next: index === articles.length - 1 ? null : articles[index + 1].node
      }
   })
})
Enter fullscreen mode Exit fullscreen mode

Now we have access to the details of previous and next articles inside article template to render links for them.

Using the pageContext

In our article template, we can destructure the props to get the pageContext like

const Article = ({ pageContext }) => {}
Enter fullscreen mode Exit fullscreen mode

Let's extract details of prev/next and save them into variables.

For previous article

const prev = pageContext.prev
   ? {
         url: `/blog/${pageContext.prev.fields.slug}`,
         title: pageContext.prev.frontmatter.title
      }
   : null
Enter fullscreen mode Exit fullscreen mode

For next article

const next = pageContext.next
   ? {
         url: `/blog/${pageContext.next.fields.slug}`,
         title: pageContext.next.frontmatter.title
      }
   : null
Enter fullscreen mode Exit fullscreen mode

Now render them on your article using jsx.

<div>
   {prev && (
      <Link to={prev.url}>
         <span>Previous</span>
         <h3>{prev.title}</h3>
      </Link>
   )}
   {next && (
      <Link to={next.url}>
         <span>Next</span>
         <h3>{next.title}</h3>
      </Link>
   )}
</div>
Enter fullscreen mode Exit fullscreen mode

That's pretty much it, with a little CSS flair you can make it look nice😉

For Reference

I've used this same logic on my gatsby blog as well. For reference, take a look at my article template and my gatsby-node.js file.

Top comments (0)