GraphQL makes it easy to get exactly the data we need for a given component. There are many times when we end up using the same query or part of a query in multiple places. This is where GraphQL Fragments can help us.
To declare a fragment we can add fragment MyAwesomeFragment on BlogPost
. The keyword fragment
tells GraphQL that we’re creating the fragment with the name, MyAwesomeFragment
. And all of this is on the type BlogPost
.
In this site I have a few different places where I’m querying images for galleries. So instead of repeating the whole query in every variation across the site I can create a queries file and drop the repeated parts in there. Here’s an example of that in action.
fragment InstaNodes on InstagramContentEdge { node { id localImage { childImageSharp { fluid(maxWidth: 1248, maxHeight: 1248) { ...GatsbyImageSharpFluid_withWebp } } } images { standard_resolution { width height url } } }}
Then we can use them in our components with a page query or static query.
const data = useStaticQuery(graphql` query { allInstagramContent( filter: { tags: { glob: "ink*2017" } } sort: { fields: created_time, order: ASC } ) { edges { ...InstaNodes } } }`);
Typing
If you’re using TypeScript you can also drop the types for the fragments in the queries file so they’re all together.
type IInstaNodes = { node: { id: string; localImage: { childImageSharp: { fluid: FluidObject; }; }; images: { standard_resolution: { width: number; height: number; url: string; }; }; };};
Bonus
Add an alias if you’re doing similar top level requests. Here’s an example of my Instagram requests.
fragment inktober2017 on Query { inktober2017: allInstagramContent( filter: { tags: { glob: "ink*2017" } } sort: { fields: created_time, order: ASC } ) { edges { ...InstaNodes } }}fragment inktober2018 on Query { inktober2018: allInstagramContent( filter: { tags: { glob: "ink*2018" } } sort: { fields: created_time, order: ASC } ) { edges { ...InstaNodes } }}fragment letterClash on Query { letterClash: allInstagramContent( filter: { tags: { eq: "letterclash" } } sort: { fields: created_time, order: ASC } ) { edges { ...InstaNodes } }}
Now we can grab that data like this:
const { inktober2017: { edges: ink2017Edges = [] } = {}, inktober2018: { edges: ink2018Edges = [] } = {}, letterClash: { edges: letterClashEdges = [] } = {},} = data;