DEV Community

Eve Porcello
Eve Porcello

Posted on

Understanding Fragments in GraphQL

This was originally posted on the Moon Highway blog.

The "QL" in GraphQL stands for the query language, and a key, yet often overlooked feature of the language is GraphQL fragments. A GraphQL query document can contain definitions for operations and fragments. Fragments are selection sets that can be reused in multiple operations.

Let's use the Snowtooth API, a fake ski resort with a real GraphQL API, to send some new queries:

query {
  Lift(id: "jazz-cat") {
    name
    status
    capacity
    night
    elevationGain
    trailAccess {
      name
      difficulty
    }
  }
  Trail(id: "river-run") {
    name
    difficulty
    accessedByLifts {
      name
      status
      capacity
      night
      elevationGain
    }
  }
}

This query requests information about the Jazz Cat lift and the River Run trail. The Lift includes name, status, capacity, night, and elevationGain in its selection set. The information that we want to obtain about the River Run trail includes a sub-selection on the Lift type for the same fields. We could create a fragment that can help us reduce redundancy in our query:

fragment liftInfo on Lift {
 name
 status
 capacity
 night
 elevationGain
}

You create fragments by using the fragment identifier. Fragments are selection sets on specific types, so you must include the type that is associated with each fragment in its definition. The fragment in this example is named liftInfo, and it is a selection set on the Lift type. When we want to add the liftInfo fragment fields to another selection set, we can do so by using three dots with the fragment name:

query {
  Lift(id: "jazz-cat") {
    ...liftInfo
    trailAccess {
      name
      difficulty
    }
  }
  Trail(id: "river-run") {
    name
    difficulty
    accessedByLifts {
      ...liftInfo
    }
  }
}

The syntax is similar to the JavaScript spread operator, which is used for a similar purpose: to assign the keys and values of one object to another. These three dots instruct GraphQL to assign the fields from the fragment to the current selection set.

In this example, we are able to select the name, status, capacity, night, and elevationGain in two different places within our query using one fragment. We would not be able to add the liftInfo fragment to the Trail selection set because it defines only fields on the Lift type. We can add another fragment for trails:

query {
  Lift(id: "jazz-cat") {
    ...liftInfo
    trailAccess {
      ...trailInfo
    }
  }

  Trail(id: "river-run") {
    ...trailInfo
    groomed
    trees
    night
  }
}

fragment trailInfo on Trail {
  name
  difficulty
  accessedByLifts {
    ...liftInfo
  }
}

fragment liftInfo on Lift {
  name
  status
  capacity
  night
  elevationGain
}

Here, we have created a fragment called trailInfo and used it in two places within our query. We’re also using the liftInfo fragment in the trailInfo fragment to select details about the connected lifts. You can create as many fragments as you want and use them interchangeably. In the selection set used by the River Run trail query, we are combining our fragment with additional details that we want to select about the River Run trail. You can use fragments in combination with other fields in a selection set. You also can combine multiple fragments on the same type in a single selection set:

query {
  allTrails {
    ...trailStatus
    ...trailDetails
  }
}

fragment trailStatus on Trail {
  name
  status
}

fragment trailDetails on Trail {
  groomed
  trees
  night
}

Another nice thing about fragments is that you can modify the selection sets used in many different queries simply by modifying one fragment:

fragment liftInfo on Lift {
 name
 status
}

This change to the selection set in the liftInfo fragment causes every query that is using this fragment to select less data. Fragments are a pretty slick feature of the GraphQL query language. Consider how you might refactor your current queries to include these compositional helpers.

If you haven't checked out my Query Language course yet on egghead.io, it covers fragments and many other features of the query language!

Top comments (1)

Collapse
 
rcapdepaula profile image
Ricardo de Paula

Hi Eve! I have a problem in iterating graphql data in ... on WpPage. I want to order the titles alphabetically.

const PageTemplate = ({ data }) =>
{ const orderdChild = [...data.wpPage.wpChildren.nodes].sort((x, y) =>
{ if (x.title < y.title) return -1 if (x.title > y.title) return 1 return 0 })
return (....

Graphql:

wpChildren {
nodes {
... on WpPage
{
id
uri
title
}
}
}

Error:
Invalid attempt to spread non-iterable instance.