Previous and Next Post using Next.js
Tags: javascript, nextjs, pagination
Published: 2022-05-10 15:10:13

I spent weeks trying to figure this out, I am not going to make you go through the same. Let's get straight into it...

## The Problem
On a Next.js site with posts fetched via graphql, how would you implement **Previous and Next POST**.  This would be on the detail view of a post.


## The Solution
> The solution below uses graphql and Contentful but can be modified to wherever you want to apply it.

```js
const ARTICLE_QUERY = `
query {
    articleCollection(order: publishedAt_DESC) {
      items {
        slug
        title
        excerpt
        category {
          title
          categorySlug
        }
        series {
          title
          slug
        }
        body {
          json
        }
      }
    }
  }
  
`;
```

```js
async function fetchGraphQL(query) {
  return fetch(
    `https://graphql.contentful.com/content/v1/spaces/${process.env.SPACE_ID}`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.CDA_TOKEN}`,
      },
      body: JSON.stringify({ query }),
    }
  )
    .then((response) => response.json())
    .catch((error) => console.error(error));
}

export async function getPostAndMorePosts(slug) {
  const response = await fetchGraphQL(ARTICLE_QUERY);
  const posts = response.data.articleCollection.items;

  const currentPost = posts.find((post) => post.slug === slug);
  const currentPostIndex = posts.findIndex((post) => post.slug === slug);
  const prevPost = posts[currentPostIndex - 1] || posts[posts.length - 1];
  const nextPost = posts[currentPostIndex + 1] || posts[0];

  if (!currentPost) {
    return {
      post: false,
    };
  }

  return {
    post: currentPost,
    morePosts: [prevPost, nextPost],
  };
}
```
In the  code above:
- We create the article query and make a function to perform our query - `fetchGraphQL`
- We then export an async function  `getPostAndMorePosts` that takes `slug` as a parameter. In it, we use `fetchGraphQL` to get all our posts as an array.
- We use **find** to get the post with the slug that matches the passed slug parameter - `currentPost` 
- Using **currentPost** as an index, we get the post before and the post after - these become our previous post and next post respectively
- Lastly, return **currentPost** as post and **morePosts** as an array of the previous and next post.


in `[slug].js`:

```js
import getPostAndMorePosts from '../../lib/api'

export async function getStaticPaths() {
  ...
}

export async function getStaticProps({ params }) {
  const data = await getPostAndMorePosts(params.slug);

  return {
    props: {
      post: data?.post ?? null,
      morePosts: data?.morePosts ?? null,
    },
  };
}

export default function Post({ post, morePosts }) {
	...
}
```
In our dynamic page:
- We import `getPostAndMorePosts` - we will use it in `getStaticProps`  after we pass the `params` from `getStaticPaths`.
- In `getStaticProps`, we pass `params.slug` to `getPostAndMorePosts` to get:
	- The current post data
	- The previous and next post data
- Lastly, we pass this data to our component and render our data.

Here is the repo with the full implementation:
https://github.com/stefanjudis/jamstack-workshop/blob/main/lib/api.js

---

## Conclusion
Thank you **[whitep4nth3r](https://twitter.com/whitep4nth3r)**, Thank you to everyone who tried to help.

> The full story of how we got here is coming in another article. It really puzzles me how there isn't a native solution for this. Gatsby has it, WordPress does as well. What happened here Next.js?

---
###  Thank you for reading, let's connect!
Thank you for visiting this little corner of mine. Let's connect on [**Twitter**](https://twitter.com/Psypher1), [**Polywork**](https://www.polywork.com/psypher1) and [**LinkedIn**](https://www.linkedin.com/in/jamesmidzi/))