I wonder what I'm doing wrong trying to create previous & next page link in my Gatsby website, below is the bug I'm trying to solve.
when I click the previous or next link instead of going to the requested page it creates the below route which is not suppose to do!
my code for Gatsby-node.js as below
const { createFilePath } = require(`gatsby-source-filesystem`)
const path = require("path")
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `Mdx`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const results1 = await graphql(`
query content {
allMdx(filter: { frontmatter: { key: { eq: "projects" } } }) {
nodes {
frontmatter {
slug
title
}
}
}
}
`)
const results2 = await graphql(`
query content {
allMdx(
filter: { frontmatter: { key: { eq: "article" } } }
sort: { fields: frontmatter___date, order: ASC }
) {
nodes {
frontmatter {
slug
title
}
}
}
}
`)
const projectTemplate = path.resolve(`./src/templates/project-details.js`)
const blogTemplate = path.resolve(`./src/templates/blog-details.js`)
if (results1.errors || results2.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
const posts = results2.data.allMdx.nodes
posts.forEach((post, index) => {
const previous = index === 0 ? null : posts[index - 1]
const next = index === posts.length - 1 ? null : posts[index + 1]
createPage({
path: `/blog/${post.frontmatter.slug}`,
component: blogTemplate,
context: {
slug: post.frontmatter.slug,
previous,
next,
},
})
})
results1.data.allMdx.nodes.forEach(node => {
createPage({
path: `/projects/${node.frontmatter.slug}`,
component: projectTemplate,
context: { slug: node.frontmatter.slug },
})
})
}
and My code for blog posts page as below
import React from "react"
import { graphql, Link } from "gatsby"
import { MDXRenderer } from "gatsby-plugin-mdx"
import { GatsbyImage, getImage } from "gatsby-plugin-image"
import Layout from "../components/Layout"
import * as styles from "../styles/blog-details.module.css"
const BlogPosts = ({ data, pageContext }) => {
console.log(pageContext)
const { body } = data.article
const { title, date, stack, featuredImg } = data.article.frontmatter
const { previous, next } = pageContext
return (
<Layout>
<div className={styles.details}>
<h2>{title}</h2>
<p>{date}</p>
<p>{stack}</p>
<div className={styles.featured}>
<GatsbyImage
image={getImage(featuredImg.childImageSharp.gatsbyImageData)}
alt={title}
/>
</div>
<article className={styles.body}>
<MDXRenderer>{body}</MDXRenderer>
</article>
{previous && (
<Link to={previous.frontmatter.slug}>
<h5>{previous.frontmatter.title}</h5>
</Link>
)}
{next && (
<Link to={next.frontmatter.slug}>
<h5>{next.frontmatter.title}</h5>
</Link>
)}
</div>
</Layout>
)
}
export default BlogPosts
export const query = graphql`
query BlogDetails($slug: String) {
article: mdx(frontmatter: { slug: { eq: $slug }, key: { eq: "article" } }) {
body
frontmatter {
slug
key
title
date
stack
featuredImg {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
}
}
`
thanks in advance for your help on this.
If I understood you correctly, the URL that is generated when clicking the previous and next buttons is "concatenating" the slug of the post to the current URL instead of replacing it, isn't it?
So, instead of creating a URL like localhost:8000/blog/next-article
is generating a localhost:8000/blog/current-article/next-article
.
This is because of the way you generate the links. You can spot the links route just by hovering the links to see that the URL of the previous/next article is being added at the end of the URL instead of replacing it.
This is because you are not adding the correct relativity to the links. Simply use:
{previous && (
<Link to={`/blog/${previous.frontmatter.slug}`}>
<h5>{previous.frontmatter.title}</h5>
</Link>
)}
{next && (
<Link to={`/blog/${next.frontmatter.slug}`}>
<h5>{next.frontmatter.title}</h5>
</Link>
)}
Starting the to
property with a slash (/
) fixes the relativity. Because your article is inside the /blog/
page you need to add it to the path.
This is the way the anchors (<a>
) work in HTML as well.