Gatsby Blog: Next and Previous Links
Published: November 18th, 2019
I wanted to add next and previous links to the bottom of my blog posts for a bit. To make this work I started by going into gatsby-node
and finding the query that is used to generate my blog posts.
This query just gets all the nodes (the markdown files) and get's the html, id and frontmatter in the form of the path name, blog title, blog date and blog tags associated with each markdown file.
allMarkdownRemark {
edges {
node {
html
id
frontmatter {
path
title
date
tags
}
}
}
}
Then I find the section of code that actually generates the blog post page. It's taking that query and looping over each node and then passing it the path and telling it what component to render.
res.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate,
});
});
The changes that I need to make are getting the next and previous from my query and then passing those into my generated pages. For allMarkdownRemark
there is an option for next
and previous
under edges
.
Adding these options under node (equal to node not inside node) in the query so I can access that information in my createPage function.
Changing the query to resemble this:
allMarkdownRemark {
edges {
node {
html
id
frontmatter {
path
title
date
tags
}
}
next {
frontmatter {
path
title
}
}
previous {
frontmatter {
path
title
}
}
}
}
Now we have access to previous and next and their frontmatter information, path and title, in the createPage function.
To update the blog post generating with our next and previous, just add them behind node. Updating the code to this:
res.data.allMarkdownRemark.edges.forEach(({ node, next, previous }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate,
});
});
Now our createPage has access to next and previous. What we can do now is pass these down to the component by using context
. Context will be an object with the information that will be passed to a component. It can then be accessed in a component by using pageContext
.
res.data.allMarkdownRemark.edges.forEach(({ node, next, previous }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate,
context: {
next,
previous,
},
});
});
Now if we go into the component and use pageContext
we can destructure it to get next and previous.
const BlogTemplate = ({ pageContext }) => {
const { next, previous } = pageContext;
const nextArticle = next && (
<Link to={next.frontmatter.path} style={{ maxWidth: '25%'}}>
<strong>Next Article</strong> <br/>
{next.frontmatter.title}
</Link>
)
const prevArticle = previous && (
<Link to={previous.frontmatter.path} style={{ maxWidth: '25%'}}>
<strong>Previous Article</strong> <br/>
{previous.frontmatter.title}
</Link>
)
}
Great! We've now got access to next and previous and can now see them in our blog posts. There is one issue that I ran into, the next and previous aren't showing the correct order of posts. The next article isn't technically the next article that's showing on the homepage.
The solution to this is to sort the query used in gatsby-node
. To display my blog posts, on the homepage I'm using a query that is sorting the posts by the frontmatter date and arranging them in descending order.
allMarkdownRemark(
sort: {
fields: frontmatter___date,
order: DESC
}
)
This should fix the issue, if you notice your next and previous are not matching up with your layout of your articles.