reactjsgraphqlgatsbyyaml-front-matter

Allow optional GraphQL data in Gatsby


I'm trying to build a Type in my gatsby-node.js file that supports an optional value. Which I think is done with [String!]!.

How can I load the new Type that I've created inside gatsby-node.js on home.js?

gatsby-node.js:

const path = require('path');
exports.createSchemaCustomization = ({ actions }) => {
    const { createTypes } = actions;
    const typeDefs = `
        type markdownRemark implements Node {
            frontmatter: Features
        }
        type Features {
            title: [String!]!
            description: [String!]!
        }
    `;
    createTypes(typeDefs);
};

pages/home/home.js:

export const query = graphql`
    query HomeQuery($path: String!) {
        markdownRemark(frontmatter: { path: { eq: $path } }) {
            html
            frontmatter {
                features {
                    title
                    description
                }
            }
        }
    }
`;

home.md:

---
path: "/"
features:
    - title: Barns
      description: Praesent commodo cursus magna vel scelerisque nisl consectetur et. Nullam id dolor id nibh ultricies vehicula ut id elit.
    - title: Private Events
      description: Praesent commodo cursus magna vel scelerisque nisl consectetur et. Nullam id dolor id nibh ultricies vehicula ut id elit.
    - title: Food and Drinks
      description: Praesent commodo cursus magna vel scelerisque nisl consectetur et. Nullam id dolor id nibh ultricies vehicula ut id elit.
    - title: Spa
      description: Praesent commodo cursus magna vel scelerisque nisl consectetur et. Nullam id dolor id nibh ultricies vehicula ut id elit.
---

This needs to work so that if the features array inside home.md's front matter is empty, then GraphQL doesn't throw an error.

Please don't tell me to always include at least one value in the array, because this isn't practical, my solution needs to support no values in my array.

I've spent two hours going through documentation/issues in circles trying to find a working solution, please can someone save me!


Solution

  • From the GraphQL docs:

    • String! means that the field is non-nullable, meaning that the GraphQL service promises to always give you a value when you query this field. In the type language, we'll represent those with an exclamation mark.
    • [Episode!]! represents an array of Episode objects. Since it is also non-nullable, you can always expect an array (with zero or more items) when you query the field. And since Episode! is also non-nullable, you can always expect every item of the array to be an Episode object.

    The exclamation point ! in GraphQL means non-nullable, so [String!]! means that there is a non-null array of non-null strings.

    If you want a field to be optional, just leave it as it is without exclamation points !. For example [String] means that the array can be null, or any of the string values inside it can be null.

    I'm also not sure that you want to be using an array in the first place, since title and description of a feature should surely just be a single string?

    As per the Gatsby docs, I think what you're looking for is this:

    const typeDefs = `
        type markdownRemark implements Node {
            // Use custom frontmatter type
            frontmatter: Frontmatter
        }
        // Define custom frontmatter type
        type FrontMatter {
          // Nullable array of Feature elements
          features: [Feature]
        }
        // Feature has nullable fields title and description
        type Feature {
            title: String
            description: String
        }
    `;
    

    This means that frontmatter has a field called features that can be null (optional) and if it does exist, is an array of Feature objects. It can be empty, but if any Feature objects exist, each Feature has a nullable (optional) title and description field.