3

I'm trying to create a blog page that can optionally display any image assets when they exist.

First, I created a content modal in Contentful with a Rich Text named "Body", and then I created an entry with some random text in it. In Gatsby, when I try to query the data via GraphQL explorer, I can query the "raw" field inside the "body". The "references" field can not be queried unless I add at least one image asset (aka, "dummy content").

below is my graphql query

export const query = graphql`
  query ($slug: String!) {
    contentfulBlog(slug: { eq: $slug }, node_locale: { eq: "en-US" }) {
      title
      body {
        raw
        references {
          ... on ContentfulAsset {
            contentful_id
            __typename
            gatsbyImageData(formats: AUTO, layout: FULL_WIDTH)
          }
        }
      }
    }
  }
`

The problem with the above query is that if there is no image asset found in a post, it will break the query. And my goal is to be able to optionally query the references field when there are assets available. But I'm not sure how to do it.

**Updated on Aug 24th, 2021:

For anyone that is also struggling with this problem as of today: After digging through tons of documentation and answers, I've found out that this is in fact one of the limitations of the gatsby-source-contentful plugin. In short, the plugin(v4), as it states in its documentation:

At the moment, fields that do not have at least one populated instance will not be created in the GraphQL schema.

Not sure if this will be addressed in a future release, but currently, it is required to have at least one dummy content(embedded image, links...etc) added in your rich text body in order for the plugin to create the "references" field in the graphql schema.

Here is the official discussion thread

York Wang
  • 1,909
  • 5
  • 15
  • 27

1 Answers1

3

If the idea is to only query references if they are available you need to customize the GraphQL schema to make the field nullable (meaning it can be empty, null) because, by default, it's inferred that it isn't.

You can check for Contentful content types in: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/content-types/content-model

This would be the ideal solution. Alternatively, according to this Medium article, you can bypass it by wrapping your offending node within a Node-type object. In your case:

export const query = graphql`
  query ($slug: String!) {
    contentfulBlog(slug: { eq: $slug }, node_locale: { eq: "en-US" }) {
      title
      body {
        raw
        references {
          ... on Node {
            ... on ContentfulAsset {
              contentful_id
              __typename
              gatsbyImageData(formats: AUTO, layout: FULL_WIDTH)
            }
          }
        }
      }
    }
  }
`

You may need to tweak it. Without knowing your data and schema structure it's impossible to guess if the query above will work alone, but get the idea. Check it in the GrahiQL playground (localhost:8000/___graphql)

Other resources:

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
  • 1
    Thank you for the help! much appreciated! – York Wang Aug 24 '21 at 06:04
  • This will only work if an extra field is added to the Content Model that houses the references separately, if you try it as part of the `references` field inside a rich text body, it will fail with the same error, as if you didn't even add 'Node' - check out the linked Medium article, a separate field called 'Content sections' is being used there as well. – benomatis Jul 29 '22 at 21:34
  • In this case, since the scenario given is a blog, the "extra content model that houses references" is added *per se*, since a blog will have a default relation with images/assets. That said, I personally prefer to customize the GraphQL schema to add/remove the nullability of the fields I need in order to avoid that issues. In a real use-case like the one described, if only one post has images it will bypass, which is pretty likely to happen. Each content model needs to be tweaked for each scenario, which in this case solved the issue – Ferran Buireu Jul 29 '22 at 21:47
  • Agreed, as a separate field will limit the placement of the reference. It's just that it is more complex to customize the GraphQL schema... :) However, in view of the above, your code block will need further explanation stating that you edited the schema, or you'd have to edit the code block to add an extra field (or indicate that your `body` field is a reference field). – benomatis Jul 29 '22 at 21:53
  • ... so much so that I am unable to, I'll have to go with the separate field solution... – benomatis Jul 29 '22 at 22:44
  • Feel free to open a new question if so. – Ferran Buireu Jul 30 '22 at 07:19