DEV Community

loading...

How to use GraphQL Fragments with Apollo

darksmile92 profile image Robin Kretzschmar ・2 min read

GraphQL requires that the queries specify the fields to return with the result to prevent over-selecting (too much fields) by design.

This means for us developers that if we design a GraphQL query, we need to write out all the fields we want to retrieve from the query node.

GraphQL itself has a really nice concept called Fragments to make life easier:

GraphQL includes reusable units called fragments. Fragments let you construct sets of fields, and then include them in queries where you need to.

This is great to use on the server side.

Here is how it looks on the server side (copied from the docs):

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}
Enter fullscreen mode Exit fullscreen mode

You can also use Fragments with Apollo on the client side!

Why? To have as less as possible lines to change when a new field is added on a type and needs to be returned! ... and of course to type the fields only once :-D

GIF of fast typing

The apollo client lets you define queries in the following syntax:

// gqlQueries.js
import gql from 'graphql-tag';

export const MY_CONTENT_QUERY = gql`
  query MY_CONTENT_QUERY($id: ID!) {
    contentDetails(id: $id) {
      id
      contentUpdated
      title
      body
      notes
      link
      tags {
        id
        name
      }
      updatedAt
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

We are already using the graphql-tag library here, so we can also use it to construct Fragments!

This example defines fragments in a separate file, imports them into the file where the queries are defined and uses them.

// gqlFragments.js
import gql from 'graphql-tag';

export const FRAGMENT_CONTENT_ALL_FIELDS = gql`
    fragment ContentAllFields on Content {
        id
        contentUpdated
        title
        body
        notes
        link
        tags {
            id
            name
        }
        updatedAt
    }
`;

Enter fullscreen mode Exit fullscreen mode
// gqlQueries.js
import gql from 'graphql-tag';
import { FRAGMENT_CONTENT_ALL_FIELDS } from './gqlFragments';

export const MY_CONTENT_QUERY = gql`
  query MY_CONTENT_QUERY($id: ID!) {
    contentDetails(id: $id) {
      ...ContentAllFields
    }
  }
  ${FRAGMENT_CONTENT_ALL_FIELDS}
`;
Enter fullscreen mode Exit fullscreen mode

My personal preferences:

Use Fragments if:

  • you query the same set of fields of a type more than once
  • you query fields of a type from which you know it could get more fields in the future that also needs to be returned
  • you refactor an existing query and add a field to it

Don't use Fragments if:

  • you are writing a PoC
  • you have less than 3 queries for a type
  • you don't always have the same fields for each query for a type

Discussion (2)

pic
Editor guide
Collapse
miketheo423 profile image
Michael Theodorou

Worked like a charm! Thanks for this.

Collapse
darksmile92 profile image
Robin Kretzschmar Author

Glad it helped :)