Skip to main content

How to use Fragments?

What are GraphQL fragments?

A GraphQL fragment is a piece of logic that can be shared between multiple queries and mutations.

Here's the declaration of a NameParts fragment that can be used with any Person object:

fragment NameParts on Person {
firstName
lastName
}

Every fragment includes a subset of the fields that belong to its associated type. In the above example, the Person type must declare firstName and lastName fields for the NameParts fragment to be valid.

We can now include the NameParts fragment in any number of queries and mutations that refer to Person objects, like so:

query GetPerson {
people(id: "7") {
...NameParts
avatar(size: LARGE)
}
}

You precede an included fragment with three periods (...), much like JavaScript spread syntax.

Based on our NameParts definition, the above query is equivalent to:

query GetPerson {
people(id: "7") {
firstName
lastName
avatar(size: LARGE)
}
}

If we later change which fields are included in the NameParts fragment, we automatically change which fields are included in operations that use the fragment. This reduces the effort required to keep fields consistent across a set of operations.

Source: Apollo client documentation

Example usage

Create a query

We'll use a query that already exists in ShipFast in a very similar form, but with fewer fields to make the example easier to read. This query returns an object of type CurrentUserType.

As you probably know, in typical apps it's possible to retrieve the current user's data through multiple different operations, including:

  • Direct query on page refresh,
  • Data returned immediately when the user successfully logs into the app,
  • Data returned immediately when the user's email is confirmed.

All of those operations will have their own GraphQL query, or mutation but we always want to have the same fields of the CurrentUserType returned. Fragments are a great way to specify the core set of those fields, like so:

Next simplify define the fragment with fields of your choice:

import { gql } from '@shipfast/webapp-api-client/graphql';

export const currentUserFragment = gql(/* GraphQL */ `
fragment currentUserFragment on CurrentUserType {
id
email
firstName
lastName
}
`);

Include the fragment in a GraphQL operation

You can include the currentUserFragment fragment in a GraphQL operation like so:

import { gql } from '@shipfast/webapp-api-client/graphql';

export const currentUserQuery = gql(/* GraphQL */ `
query currentUserQuery {
currentUser {
id
...currentUserFragment
}
}
`);

Query data in a component

ShipFast uses [Codegen](https://the-guild.dev/graphql/codegen) to generate typed queries, mutations, subscriptions, and GraphQL resolvers. Additionally, it uses [client-preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) plugin to integrate with Apollo GraphQL client.

This plugin has Fragment Masking enabled by default. It means that in order to get fragment's data you need to use the automatically generated getFragmentData helper function, like so:

import { useQuery } from '@apollo/client';
import { getFragmentData } from '@shipfast/webapp-api-client/graphql';

const UserProfile = () => {
const { data } = useQuery(currentUserQuery, {
nextFetchPolicy: 'network-only',
});
const profile = getFragmentData(currentUserFragment, data?.currentUser);

return (
<span>
{profile.firstName} {profile.lastName}
</span>
);
};

Otherwise, TyperScript compiler would throw an error if you tried to access data.firstName directly.

Advanced fragments usage

Fore more advances fragments usage, make sure you check the Apollo client documentation.