Search code examples
reactjsgraphqlgatsbycontentfulrichtext

How to optionally query references in gatsby Contentful Rich Text?


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


Solution

  • 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: