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

Posted

技术标签:

【中文标题】如何基于 GraphQL API 的 slug 使用 Next.js 进行动态路由?【英文标题】:How do I do dynamic routing with Next.js based on slug from GraphQL API? 【发布时间】:2021-04-25 09:08:15 【问题描述】:

我很难理解基于变量的动态路由。我可以使用 Next.js 获取具有动态路由的单个页面的集合中的项目列表,但不能获取单个项目及其字段。

背景

我有一个带有 GraphQL API 的 KeystoneJS 无头 CMS。我正在尝试创建一个包含帖子列表和单个帖子页面的简单博客。我已经能够查询并返回一个帖子列表,但我需要根据 slug 字段获取一个单独的帖子,以便可以通过/posts/[slug].js 访问它。

我尝试过的

我一直在使用 Apollo Client 来处理查询。我有一个连接到 API 的 apolloClient.js 文件:

// apolloClient.js
import  ApolloClient, InMemoryCache  from "@apollo/client";

export default new ApolloClient(
  uri: "http://localhost:3000/admin/api",
  cache: new InMemoryCache(),
);

我有一个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;
    );

最后,在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  ;

显然,这是行不通的。我不能正确地将变量(我假设是 slug)传递到查询中,并且阅读了几个教程后,我仍然无法理解它。有谁知道我做错了什么?

【问题讨论】:

几件事:1)在getStaticPaths 中,您将await getAll() 保存到lingo,但随后映射posts 变量,这是一个错字吗? 2) 在getStaticProps 中对getBySlug 调用执行相同的操作,使用term 变量但随后返回post 是的,从错误的文件中复制了代码,谢谢。我已经更新了原始问题中的代码。我也有同样的问题。什么都没有回来。 【参考方案1】:

getStaticPaths 中,params 对象中返回的键需要匹配动态路由命名。在您的情况下,由于您使用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  ;

编辑:关于请求问题,对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;
    );

【讨论】:

谢谢。我已经更新了我的代码,但我得到了错误:Error: Response not successful: Received status code 400。这表明我的查询在post.service.js 中是错误的?我的论点错了吗? 是的,这意味着请求有问题。 好的,谢谢!我将单独问一个关于如何通过 slug 查询 API 的问题,因为我不知道查询如何知道 slug 是什么。 这有帮助吗:***.com/a/51523848/1870780?您不应该将额外的variables 对象传递给apolloClient.query() 调用吗?请注意,我的 GraphQL 知识有限。 谢谢。是的,它帮助我更好地编写查询。我的查询仍然出现 Apollo 错误,因此我已向here 寻求帮助。

以上是关于如何基于 GraphQL API 的 slug 使用 Next.js 进行动态路由?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 GraphQL 通过 slug 进行搜索? - 字段“文章”上的“未知参数”

如何在使用 graphql 和 mongodb 的查询中使用“where”参数?

GraphQL 请求错误 - 未知参数“slug”

动态 slug 未使用 graphql 和 nuxt 填充 url

GraphQL / Strapi - 无法按字符串字段过滤

在 Gatsby 中从 graphQL 查询创建 slug