Search code examples
reactjsgraphqlgatsbycontentful

Contentful GraphQL Destructuring Fragments in Array


Got an issue with fragments, in a graphql query for a gatsby site I am working on that uses Contentful as the CMS:

Consider the following query:

export const query = graphql`
    query ComposablePageQuery($slug: String!) {
        contentfulPage(slug: { eq: $slug }) {
            __typename
            contentful_id
            slug
            sections {
                __typename
                contentful_id
                ... on ContentfulModelA {
                    fieldA
                    fieldB
                }
                ... on ContentfulModelB {
                    fieldC
                    fieldD
                }
            }
        }
    }
`;

Now the sections variable, is an array that can accept different model references, in my case, I have two models, ModelA and ModelB, with trivial fields for the sake this question.

The trouble is that unless at least one instance of each is included in the sections array on the particular page, I get the following error:

There was an error in your GraphQL query:

Fragment cannot be spread here as objects of type "ContentfulModelA" can never be of type "ContentfulModelB".

If the sections array has instances of both models present, then there is no problem.

So how can this be addressed, I want the query to handle the case that ModelA OR ModelB may be present in the list, but without guarantee. Seems like a reasonable request given that in web design, it's foreseeable that a particular page may be rich in one particular model, and completely void of the other, and a different page vice-versa, and another page may combine both.

I have tried declaring fragments explicitly too, and replacing the inline fragment usage illustrated above, but the same error persists.

--

NB: One workaround is to create dummy records instances of each model and include in the array. the models would be modified to include a boolean variable to illustrate that it shouldn't be actually used, then these dummy instances get filtered out on the frontend. However, this would have to be done on each and every page, and it seems to be an approach that is rather like trying to thread a needle with a sledge hammer. Surely there is a better workaround. What happens when there is dozens of different models that can be added to the array.

--


Solution

  • I believe you'll want to define a Section type as a union of ContentfulModelA and ContentfulModelB

    union Section = ContentfulModelA | ContentfulModelB