简体   繁体   English

如何根据 GraphQL API 的 slug 使用 Next.js 进行动态路由?

[英]How do I do dynamic routing with Next.js based on slug from GraphQL API?

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.我能够获取集合中的项目列表,但不能获取单个项目及其单个页面的字段,该页面具有 Next.js 的动态路由。

Background背景

I have a KeystoneJS headless CMS with a GraphQL API.我有一个带有 GraphQL API 的 KeystoneJS 无头 CMS。 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 .我已经能够查询并返回帖子列表,但我需要根据 slug 字段获取单个帖子,以便可以在/posts/[slug].js访问它。

What I've tried我试过的

I've been using Apollo Client to handle the queries.我一直在使用 Apollo Client 来处理查询。 I have an apolloClient.js file that connects to the API:我有一个连接到 API 的apolloClient.js文件:

// 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文件来查询 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:最后,在posts/[slug].js我试图像这样返回数据:

//[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.我不能将变量(我假设它是 slug)正确地传递到查询中,并且阅读了几个教程后,我仍然无法理解它。 Does anyone see what I'm doing wrong?有谁看到我做错了什么?

In getStaticPaths the keys returned in the params objects need to match the dynamic route naming.getStaticPaths中, params对象中返回的键需要与动态路由命名相匹配。 In your case, since you're using posts/[slug].js for the route, you'd need to return params with the format { slug: post.slug } .在您的情况下,由于您使用posts/[slug].js作为路由,因此您需要返回格式为{ slug: post.slug } params

export async function getStaticPaths() {
  const posts = await getAll();

  const paths = posts.map((post) => ({
    params: { slug: post.slug }, // Rename to `slug`
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const post = await getBySlug(params.slug); // Rename to `params.slug`

  return { props: { post } };
}

Edit: Regarding the request issue, the following change to getBySlug should make it work as expected.编辑:关于请求问题,对getBySlug的以下更改应使其按预期工作。

export async function getBySlug(slug) {
  return apolloClient
    .query({
      query: gql`
        query Post($slug: String){
          post(slug: $slug) {
            id
            title
            lead
            body
          }
        }
      `,
      variables: {
        slug
      }
    })
    .then((result) => {
      return result.data.Post;
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM