首页 > 解决方案 > 使用 getEntry() 帮助程序到达 Contentful 的 API 时出现问题:未从已找到条目的承诺中返回任何内容

问题描述

介绍

几天前,我在这里发布了一个问题,寻求有关内容 API 的帮助,以对对象进行 javascript 查询,从那时起,我一直在努力理解有关 NextJS 使用此 API 的一件事。

这里的交易是contentfulpackage: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(),映射部分的代码可以访问该组件数组,但不会返回它的内容:

// 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()promise 不会返回我似乎可以在我的页面中使用的值。

// ./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>
      )

控制台没有返回错误,并且我的页面结构不会使用该 slug 呈现跨度:

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

这是一个已回答的问题,说明这getEntry()是达到该内容的正确方法,我已经非常努力地尝试了这种方法,但没有成功。其他人说要查询getEntries()并再次尝试,但没有成功。

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

不知道如何进行。我是否应该以另一种方式重新考虑整个事情,甚至尝试 GraphQL API?从来没有在盖茨比之外使用过,即使我不是专家。非常感谢您对此事的任何想法以及有关如何进行的建议。

标签: javascriptreactjsnext.jscontentfulcontentful-api

解决方案


内容丰富的 DevRel 在这里。

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

要在嵌套中访问多于一级的链接,您必须定义查询include参数include默认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]
    }
  }
}

推荐阅读