#reactjs #graphql #gatsby #netlify #contentful
#reactjs #graphql #gatsby #netlify #удовлетворительный
Вопрос:
Мне нужна помощь с запросом Graphql :). Я пытаюсь развернуть веб-сайт портфолио в Netlify, и во время развертывания я получаю эту ошибку. Мой код работает на localhost, но не на Netlify. Мне нужно извлечь данные из содержимого и заполнить ими галерею изображений.
Ожидаемый результат: Netlify развернет мой код
Результат, который я получил: ошибка сборки.
There was an error in your GraphQL query:
2:51:25 AM: Cannot query field "tags" on type "ContentfulArt".
2:51:25 AM: If you don't expect "tags" to exist on the type "ContentfulArt" it is most likely a typo.
However, if you expect "tags" to exist there are a couple of solutions to common problems:
2:51:25 AM: - If you added a new data source and/or changed something inside gatsby-node.js/gatsby-config.js, please try a restart of your development server
2:51:25 AM: - The field might be accessible in another subfield, please try your query in GraphiQL and use the GraphiQL explorer to see which fields you can query and what shape they have
2:51:25 AM: - You want to optionally use your field "tags" and right now it is not used anywhere. Therefore Gatsby can't infer the type and add it to the GraphQL schema. A quick fix is to add at least one entry with that field ("dummy content")
2:51:25 AM: It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned "dummy content". Visit our docs to learn how you can define the schema for "ContentfulArt":
https://www.gatsbyjs.org/docs/schema-customization/#creating-type-definitions
Gatsby-node.js файл
enter code here
const path = require('path')
module.exports.createPages = async ({graphql, actions}) => {
const { createPage } = actions
const portfolioTemplate = path.resolve('./src/templates/gallerylist.js')
const { data } = await graphql(
`
query{
allContentfulArt{
edges{
node{
title
tags
publishedDate(formatString:"MMMM Do, YYYY")
image{
file{
url
}
}
}
}
}
}
`
)
//error handling
//amount of images per page = 8
const imgPerPage = 8
const numPages = Math.ceil(data.allContentfulArt.edges.length / imgPerPage)
//we calculate math ceiling from the total amount of objects in our query by edges.length then divide it by 8.
//we create page for each index in Numpages, ignoring the callback with "_,", path = path where we will create pages
//component - template that contain the endpoints for our create page code
//context - information to pass down into the created page
Array.from({length:numPages}).forEach((_, i) => {
actions.createPage({
path: i === 0 ? `/portfolio/${1}` : `/portfolio/${i 1}`,
component:portfolioTemplate,
context: {
limit: imgPerPage,
skip: i * imgPerPage,
numPages,
currentPage: i 1
}
})
})
}
Мой файл шаблона
import React from 'react'
import {graphql} from 'gatsby'
import Zoom from 'react-medium-image-zoom'
import Footer from '../components/footer'
import Header from '../components/header'
import Head from '../components/head'
import 'react-medium-image-zoom/dist/styles.css'
import Pagination from '../components/pagination'
import portfolioStyles from '../pages/portfolio.module.scss'
const GalleryList = ({ pageContext, data}) => {
const {currentPage, numPages} = pageContext
const isFirst = currentPage === 1
const isLast = currentPage === numPages
/*if prev page equals to currentpage -1 we return return to the first page, otherwise we go down 1 page*/
const prevPage = currentPage - 1 === 1 ? `/portfolio/${1}` : `/portfolio/${currentPage - 1}`
/*next page = currentpage 1*/
const nextPage = `/portfolio/${currentPage 1}`
/* this will return a div container that conain gallery page
we are passing data via different predefined constants and variables
*/
return (
<div className={portfolioStyles.maincontainergallery}>
<Head title="Gallery" />
<div className={portfolioStyles.headercomponent}>
<Header />
{/* Header container that includes menu and a pagination */}
<div className={portfolioStyles.portfoliopagepaginationcontainer}>
{/* This is pagination component with passed down props to manage the pagination */}
<Pagination
isFirst={isFirst}
isLast={isLast}
prevPage={prevPage}
nextPage={nextPage}/>
</div>
</div>
{/* This is a gallery div container that receives data from Graphql query*/}
<div className={portfolioStyles.portfoliopagegallerycontainer}>
<div className={portfolioStyles.portfoliopagegallery}>
{
data.allContentfulArt.edges.map((edge) => {
return (
//we grabbing data from Contenful API using Graphql query
//Zoom allows us to click-zoom the images passed down from Contenftul API
<figure className={portfolioStyles.portfoliopagegalleryfigure} >
<h3 >
<figcaption>
{edge.node.title}
</figcaption>
</h3>
<p>{edge.node.tags}</p>
<p>{edge.node.publishedDate}</p>
<Zoom>
<img src={edge.node.image.file.url} width="250" alt={edge.node.title}/>
</Zoom>
</figure>
)
})
}
</div>
</div>
{/* this is a footer container with a footer component */}
<div className={portfolioStyles.portfoliopagefootercontainer}>
<Footer />
</div>
</div>
)
}
/* This is graphql query to grab the code from a Contentful API */
export const pageQuery = graphql`
query($skip: Int!, $limit: Int!){
allContentfulArt(skip: $skip, limit: $limit){
edges{
node{
title
tags
publishedDate(formatString:"MMMM Do, YYYY")
image{
file{
url
}
}
}
}
}
}`
export default GalleryList
Ответ №1:
Это связано с тем, что ваша схема allContentfulArt
содержимого определила tags
поле как строку и по умолчанию не может быть обнуляемым. Он всегда ожидает, что результат будет заполнен, по крайней мере, для одного contentfulArt
.
Идеальным решением является настройка вашей схемы путем добавления определения типа
Одна простая вещь, которую вы можете временно сделать, чтобы обойти проблему, — это добавить значение для вашего tags
поля или добавить значение пробела и обрезать его раньше, после получения ваших данных.
Комментарии:
1. Привет, Ферран, я попытался добавить схему, но все равно получил ту же ошибку. 🙁 Я ничего не могу найти о фиктивном контенте и не понимаю, почему он не работает на веб-сайте, когда он явно работает на локальном хосте:(
2. Вы добавили переменные среды в Netlify с префиксом
GATSBY_
?3. Просто попытался добавить префикс GATSBY_ к переменным env в netlify. Та же сделка 🙂
4. Я решил проблему, изменив allContentfulArt на AllcontentfulAssets
Ответ №2:
Во-первых, убедитесь, что у вас есть экземпляр tags
в ваших данных.
В настоящее время есть некоторые вещи, которые следует учитывать при создании моделей контента в Contentful.
- На данный момент поля, у которых нет хотя бы одного заполненного экземпляра, не будут созданы в схеме GraphQL.
- При использовании ссылочных полей имейте в виду, что этот исходный плагин автоматически создаст обратную ссылку. Вам не нужно создавать ссылки для обоих типов контента.
Это то, что ваше сообщение об ошибке пыталось передать с помощью этого сообщения:
Вы хотите дополнительно использовать свое поле «теги», и сейчас оно нигде не используется. Поэтому Gatsby не может определить тип и добавить его в схему GraphQL. Быстрое решение — добавить хотя бы одну запись с этим полем («фиктивное содержимое»). Рекомендуется явно ввести вашу схему GraphQL, если вы хотите использовать необязательные поля. Таким образом, вам не нужно добавлять упомянутое «фиктивное содержимое». Посетите наши документы, чтобы узнать, как вы можете определить схему для «ContentfulArt»
Во-вторых, убедитесь, что tags
они доступны.
Если вы используете API предварительного просмотра для извлечения черновиков в процессе разработки, вполне вероятно, что вы не опубликовали содержимое, tags
установленное в Contentful. При развертывании в рабочей среде и извлечении из API без предварительного просмотра ваш черновик содержимого будет недоступен.
Наконец, убедитесь, что вы настроили переменные среды в Netlify для включения вашего токена доступа к содержимому.
Комментарии:
1. Я попытался добавить схему, и я все еще получил ту же ошибку. 🙁 Я ничего не могу найти о фиктивном контенте и не понимаю, почему он не работает на веб-сайте, когда он явно работает на локальном хосте:(
2. Я не знаю, что вы имеете в виду, вы ничего не можете найти. Я скопировал соответствующие разделы документации и ошибки в свой ответ для вас. Просто прочитайте мой ответ и следуйте ему.
3. Я решил проблему, изменив allContentfulArt на AllcontentfulAssets
4. @AlexVoznesenski я на 100% уверен, что это не так (GraphQL чувствителен к регистру, а имена полей в корневом объекте запроса в Gatsby имеют нижний регистр), но, возможно, вы имеете в виду
allContentfulAssets
.