使用 getEntry() 帮助程序到达 Contentful 的 API 时出现问题:已找到条目的承诺未返回任何内容

Problem reaching Contentful's API with getEntry() helper: no content is returned from promise of found entry

简介

几天前,我发布了一个 question here 请求帮助 API 查询对象 javascript 从那时起我一直在努力理解关于这个的一件事API 与 NextJS 一起使用。

这里的交易是 contentful 包提供了两个助手:getEntries()getEntry()。第一个确实帮助我获取了我正在工作的页面的内容,但我觉得由于内容模型的结构,我在获取此页面中的链接条目时遇到了问题。

工作代码

我在单独的文件中设置了 contentfulClient,但为了便于解释,让我将两者连接起来:

import Head from 'next/head'

// ./lib/contentful-client.js
const { createClient } = require('contentful')

const contentfulClient = createClient({
  space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE,
  accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN
})

module.exports = contentfulClient

// ./pages/index.js
export async function getStaticProps() {
  let data = await contenfulClient.getEntries({
    content_type: 'page',
    'field.slug': 'page_slug'   // <-- this is being manually set for each page
  })
  return {
    props: {
      pagina: data.items[0]     // <-- where the props are build and exported
    }
  }
}

export default function HomePage({ pagina }) {

  const { title, slug, sections } = pagina.fields

  return (
    <div>
      <Head>
        <title>{title}</title>
      </Head>
      <main id={slug}>
        {sections.map((section) => {
          console.log(section)
        })}
      </main>
    </div>
  )
}

这将为构建页面的每个部分获取内容。控制台会在一定程度上显示实际结构的日志,这就是问题所在。

内容模型结构

页面的实际内容模型是为用户提供灵活性而开发的,可以选择是否为部分提供图像附件,或者构建具有其他属性的另一个组件。

├── Page
|     ├── title
|     ├── slug
|     └── section
|           ├── title
|           ├── slug
|           ├── content
|           └── components
|                 ├── imageComponent
|                 ├── formComponent
|                 └── extraComponent
.                     .
.                     .
.                     .

使用前面的函数 getStaticProps(),映射部分的代码可以访问该组件数组,但不会return它的内容:

// console output
{sys: {…}, fields: {…}}
  fields:
    componentes: Array(3)
      0:
        sys: {type: "Link", linkType: "Entry", id: "X1n2uZJfMMwtJbY3H7Z6M"}
        __proto__: Object
        1:
        sys: {type: "Link", linkType: "Entry", id: "19gYv80phM75jgmAKCgwAI"}
        __proto__: Object
        2:
        sys: {type: "Link", linkType: "Entry", id: "4xCKnCVG142Mxl9s1iNsPZ"}
        __proto__: Object
        length: 3
        __proto__: Array(0)

因此,为了做到这一点,我意识到 getEntry(<entry_id>) 是获取该内容的好方法,或许可以将其转换为 json 结构。

// ./pages/index.js
return (
    <div>
      <Head>
        <title>{title}</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main id={slug}>
        {secoes.map((secao) => {
          contentfulClient.getEntry(secao.sys.id)
            .then((entry) => console.log(entry))
            .catch((err) => console.error(err))
        })}

      </main>
      <footer >
        (footer)
      </footer>
    </div>
  )

// console output
{sys: {…}, fields: {…}, toPlainObject: ƒ}
  fields:
    slug: "hero"
    title: "This is my title!"
    components: Array(3)
      0:
        fields:
          main: Array(2)
            0:
              fields:
                file:
                  contentType: "image/png"
                  details: {size: 188420, image: {…}}
                  fileName: "bkgHero.png"
                  url: "<path_to>/bkgHero.png" // <-- can reach the paths for images, for instance. 
                  __proto__: Object
                title: "heroBkg"
                __proto__: Object
              sys:
                createdAt: "2020-06-08T15:18:42.394Z"
                environment: {sys: {…}}
                id: "5E2h7vNFAFTW4BYKWPJo9E"
                locale: "pt-BR"
                revision: 3
                space: {sys: {…}}
                type: "Asset"
                updatedAt: "2020-06-30T19:05:51.537Z"
                __proto__: Object
              __proto__: Object

“损坏”的代码

好吧,它并没有真的坏掉。它记录下来,我可以看到这些对象的所有内容,但我不能把我的手指放在上面,因为 .then() 承诺不会 return 我似乎可以在我的页面中使用的值。

// ./pages/index.js
    return (
        <div>
          <Head>
            <title>{title}</title>
            <link rel="icon" href="/favicon.ico" />
          </Head>
          <main id={slug}>
            {secoes.map((secao) => {
              contentfulClient.getEntry(secao.sys.id)
                .then((entry) => <span>{entry.fields.slug}</span>) // <-- Trying to fetch content from that entry
                .catch((err) => console.error(err))
            })}
    
          </main>
          <footer >
            (footer)
          </footer>
        </div>
      )

控制台没有 return 错误,我的页面结构不会呈现带有该 slug 的跨度:

<div id="__next">
  <div>
    <main id="index"></main>
    <footer>(footer)</footer>
  </div>
</div>

an answered question here telling that getEntry() is the proper way to reach that content and I've tried really hard with that method with no sucess. 可以用 getEntries() 查询并再次尝试,但没有成功。

我认为这里的主要问题是 NextJS 强制我获取索引中的这些内容,以便通过 props 传递到我的页面的组件,理论上它应该以两种方式工作,因为两种方式都将 return 我在日志中的内容。我只是无法将其作为道具或数据链获取。

不确定如何进行。我是否应该以另一种方式重新考虑这整件事,甚至尝试 GraphQL API?从来没有在 Gatsby 之外使用过它,即便如此我也不是专家。 如果您对此有任何想法以及如何进行的建议,我们将不胜感激。

此处内容丰富的 DevRel。

查看代码以及您如何使用 getStaticProps 看起来对我来说是有效的并且是要走的路,imo。

要访问嵌套中向下一层以上的链接,您必须定义 the include query parameterinclude 默认为 1 这解释了为什么您可以访问 sections 但不能访问 components 的内容。在处理嵌套内容结构时,建议增加包含的嵌套级别数。

// ./pages/index.js
export async function getStaticProps() {
  let data = await contenfulClient.getEntries({
    content_type: 'page',
    'field.slug': 'page_slug'
    include: 5 // <-- this defaults to 1
  })
  return {
    props: {
      pagina: data.items[0]
    }
  }
}