Joel M. Turner

Illustration

Blog

Notes

Quick Tip: GraphQL Fragments in Gatsby

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.

1fragment InstaNodes on InstagramContentEdge {
2 node {
3 id
4 localImage {
5 childImageSharp {
6 fluid(maxWidth: 1248, maxHeight: 1248) {
7 ...GatsbyImageSharpFluid
8 }
9 }
10 }
11 images {
12 standard_resolution {
13 width
14 height
15 url
16 }
17 }
18 }
19}

Then we can use them in our components with a page query or static query.

1const data = useStaticQuery(graphql`
2 query {
3 allInstagramContent(
4 filter: { tags: { glob: "ink*2017" } },
5 sort: { fields: created_time, order: ASC }) {
6 edges {
7 ...InstaNodes
8 }
9 }
10 }
11`)

Typing

If you’re using TypeScript you can also drop the types for the fragments in the queries file so they’re all together.

1type IInstaNodes = {
2 node: {
3 id: string;
4 localImage: {
5 childImageSharp: {
6 fluid: FluidObject;
7 }
8 }
9 images: {
10 standard_resolution: {
11 width: number;
12 height: number;
13 url: string;
14 }
15 }
16 }
17}

Bonus

Add an alias if you’re doing similar top level requests. Here’s an example of my Instagram requests.

1fragment inktober2017 on Query {
2 inktober2017: allInstagramContent(
3 filter: { tags: { glob: "ink*2017" } }
4 sort: { fields: created_time, order: ASC } ) {
5 edges {
6 ...InstaNodes
7 }
8 }
9}
10fragment inktober2018 on Query {
11 inktober2018: allInstagramContent(
12 filter: { tags: { glob: "ink*2018" } }
13 sort: { fields: created_time, order: ASC } ) {
14 edges {
15 ...InstaNodes
16 }
17 }
18}
19fragment letterClash on Query {
20 letterClash: allInstagramContent(
21 filter: { tags: { eq: "letterclash" } }
22 sort: { fields: created_time, order: ASC } ) {
23 edges {
24 ...InstaNodes
25 }
26 }
27}

Now we can grab that data like this:

1const {
2 inktober2017: { edges: ink2017Edges = [] } = {},
3 inktober2018: { edges: ink2018Edges = [] } = {},
4 letterClash: { edges: letterClashEdges = [] } = {},
5 } = data
Discuss this article on Twitter