I'm having a tough time getting my head around dynamic routing based on variables. I'm able to get a list of items in a collection but not an individual item and its fields for an individual page with a dynamic route with Next.js.
Background
I have a KeystoneJS headless CMS with a GraphQL API. I'm trying to create a simple blog with a list of posts and an individual post page. I have been able to query and return a list of posts, but I need to get an individual post based on the slug field so it can be accessed at /posts/[slug].js
.
What I've tried
I've been using Apollo Client to handle the queries. I have an apolloClient.js
file that connects to the API:
// apolloClient.js
import { ApolloClient, InMemoryCache } from "@apollo/client";
export default new ApolloClient({
uri: "http://localhost:3000/admin/api",
cache: new InMemoryCache(),
});
I have a post.service.js
file to query the API:
// post.service.js
import { gql } from "@apollo/client";
import apolloClient from "../_utils/apolloClient";
export async function getAll() {
return apolloClient
.query({
query: gql`
query {
allPosts {
id
term
slug
}
}
`,
})
.then((result) => result.data.allPosts);
}
export async function getBySlug(slug) {
return apolloClient
.query({
query: gql`
query {
Post(slug: $slug) {
id
title
lead
body
}
}
`,
})
.then((result) => {
return result.data.Post;
});
}
And finally, in posts/[slug].js
I am trying to return the data like so:
//[slug].js
import Head from "next/head";
import { ApolloClient, InMemoryCache, gql } from "@apollo/client";
import { getAll, getBySlug } from "../../_services/post.service";
export default function Post({ post }) {
return (
<div>
<Head>
<title>Launchpad</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1>{post.term}</h1>
</main>
<footer>
<p>{post.lead}</p>
</footer>
</div>
);
}
export async function getStaticPaths() {
const posts = await getAll();
const paths = posts.map((post) => ({
params: { id: post.slug },
}));
return { paths, fallback: false };
}
export async function getStaticProps({ params }) {
const post = await getBySlug(params.id);
return { props: { post } };
}
Obviously, this doesn't work. I must not be passing the variable (which I'm assuming is the slug) into the query properly and having read several tutorials I still can't get my head around it. Does anyone see what I'm doing wrong?
getStaticPaths
you're savingawait getAll()
tolingo
but then mapping theposts
variable, is this a typo? 2) Doing the same ingetStaticProps
for thegetBySlug
call, using theterm
variable but then returningpost
. – Flatto