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.

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;

Discuss this article on Twitter

Category:

dev

Tags:

GatsbyGraphQLReactquick tip
Build a React Gallery With CSS Grid

© 2012-2022, built with Next.js and Chakra UI

Instagramtwittergithubjoelmturner's DEV Profile