Проблема с доступом к API Contentful с помощью хелпера getEntry(): из обещания найденной записи не возвращается контент

вступление

Несколько дней назад я разместил здесь вопрос с просьбой о помощи с контентным 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.info(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.info(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() не вернет значение, которое я могу использовать на своей странице.

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

Из консоли не возвращается ошибка, и моя структура страницы не будет отображать диапазон с этим слагом:

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

Это ответ на вопрос здесь , говорящий, что getEntry() - это правильный способ получить доступ к этому контенту, и я очень старался с этим методом, но безуспешно. Другие говорят запрашивать с getEntries() и тоже пробовали, но безуспешно.

Я считаю, что основная проблема здесь заключается в том, что NextJS заставляет меня извлекать это содержимое в индексе, чтобы передавать реквизиты компонентам моей страницы, и теоретически это должно работать в обоих направлениях, потому что оба способа вернут мне содержимое в журнал. Я просто не могу связаться с ним как с реквизитом или в цепочке данных.

Не знаю, как действовать. Должен ли я переосмыслить все это по-другому или даже попробовать GraphQL API? Никогда не использовал это за пределами Гэтсби, и даже в этом я не эксперт. Буду признателен за любые мысли по этому поводу и предложения о том, как действовать.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 230
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Контент DevRel здесь. 👋

Глядя на код и то, как вы подошли к использованию getStaticProps, мне кажется, что это правильный путь, имхо.

Чтобы получить доступ к ссылкам более чем на один уровень ниже во вложенности, вы должны определить параметр включения запроса. 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]
    }
  }
}

Привет @stefan-judis. Вы помогли мне с моим предыдущим вопросом. Еще раз спасибо за поддержку здесь. Я пытался установить его на 5 и не повезло. Пришлось увеличить досягаемость до 6, и тогда я смог получить это содержимое. Здорово знать, что это просто. Мне интересно, есть ли ограничение на значение включения, которое мы можем установить. Может 10? Просто любопытно.

Eduardo Oliveira 15.12.2020 12:21

Это 10. :) Вы найдете больше информации в связанных документах. Если у вас возникнут дополнительные вопросы, мы всегда готовы ответить на contentful.com/slack.

stefan judis 15.12.2020 12:45

Другие вопросы по теме