Organize Your GraphQL Calls with Fragments
graphql
gatsby
In my last post, I walked through how you could render components in React based on content from your CMS. In the GraphQL calls I went through as examples, I listed out all the content types I would call in Contentful. The problem with our implementation is scaling. As we add more content types, or locations where content types get referenced, we need to add more to our GraphQL calls. In this post, I wanted to show how to clean up those calls with fragments. Fragments let you break up your GraphQL calls into reusable components. We can leverage these to allow for cleaner, more scalable code.
Pre-Fragment Implementation
Our original implementation was the following:
query MyQuery {
contentfulStandardPage(slug: {eq: "about-us"}) {
title
blocks {
... on ContentfulHeroBlock {
id
name
title
image {
image {
fluid {
src
}
}
}
}
... on ContentfulTextBlock {
id
bodyContent {
bodyContent
}
}
}
}
}
If we start from the top and work our way down, we can see our code starts out with specifying our call for a Contentful content type we call Standard Page. We added a filter on the slug, indicating we want the "About" page. Next we get into the fields. There are only two fields we want on from the Standard Page, title and blocks. The title field is pretty self explainatory. The blocks field is where we can clean things up.
The Fragment
The way we build the fragments is exactly how we implement parts of the original GraphQL call. We separate it into a separate file. Here, we have an example using the HeroBlock:
import { graphql } from "gatsby"
export const HeroBlockQuery = graphql`
fragment HeroBlock on ContentfulHeroBlock {
id
title
subtitle
sys {
contentType {
sys {
id
}
}
}
image {
altText
image {
fluid {
...GatsbyContentfulFluid
}
}
}
}
We start off by declaring this as a fragment called HeroBlock. From there we make a regular GraphQL call for the HeroBlock. All of this is assigned to a variable we call HeroBlockQuery we set to export.
Original Call with Fragments
Now lets take that original call to get the StandardPage and replace all that code for content types with fragments:
export const pageQuery = graphql`
query PageBySlug($slug: String!) {
contentfulStandardPage(slug: {eq: $slug}) {
blocks {
__typename
... on Node {
... HeroBlock
... TextBlock
}
}
}
}
`;
We are able to incorporate the fragments, and cut the number of lines in our call for content types from over twenty to two.
Final Thoughts
Hopefully these examples demonstrate the value of fragments. Any opportunity to make code cleaner and more reusable is a win. I have these and a some other example fragments in my Github gists if you want to check them out. If you have any questions or need any help with your implementation, feel free to reach out.