GraphQL Core: Fragments And Directives #8

Deep dive into the GraphQL Fragments And Directives and how to work with them


On this page, you'll learn in detail about Core concepts of GraphQL. In this post, we will look into below concepts
  • Fragments
  • Directives

Fragments

Let's say we had a relatively complicated page in our app, which let us look at two heroes side by side, along with their friends. You can imagine that such a query could quickly get complicated because we would need to repeat the fields at least once - one for each side of the comparison.

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

Here's an example of how you could solve the above situation using fragments:
{
empireHero: person(id: 1) {
...PersonFields #include fields from fragment defined height #query extra fields as required mass #query extra fields as required
}

jediHero: person(id: 4) {
...PersonFields
}
}


fragment PersonFields on Person {
name
gender
birth_year
starships {
name
}
}

Fragments are reusable query that can be embedded into another query, without duplication same query again and again:

You can see how the above query would be pretty repetitive if the fields were repeated. The concept of fragments is frequently used to split complicated application data requirements into smaller chunks, especially when you need to combine lots of UI components with different fragments into one initial data fetch.

It is possible for fragments to access variables declared in the query or mutation. See variables.
fragment PersonFields on Person { name gender birth_year
height(unit: $unit) starships { name } }
. . .

Directives

We discussed above how variables enable us to avoid doing manual string interpolation to construct dynamic queries. Passing variables in arguments solves a pretty big class of these problems, but we might also need a way to dynamically change the structure and shape of our queries using variables.

For example, we can imagine a UI component that has a summarized and detailed view, where one includes more fields than the other.

Let's construct a query for such a component:
{
persons {
name
age
id
friends @include(if: true) {
name
id
age
}
}
}

Try editing the variables above to instead pass false for friends, and see how the result changes:
We needed to use a new feature in GraphQL called a directive. A directive can be attached to a field or fragment inclusion and can affect execution of the query in any way the server desires. The core GraphQL specification includes exactly two directives, which must be supported by any spec-compliant GraphQL server implementation:
  • @include(if: Boolean) Only include this field in the result if the argument is true.
  • @skip(if: Boolean) Skip this field if the argument is true.

Directives can be useful to get out of situations where you otherwise would need to do string manipulation to add and remove fields in your query. Server implementations may also add experimental features by defining completely new directives.
. . .

Meta fields

Given that there are some situations where you don't know what type you'll get back from the GraphQL service, you need some way to determine how to handle that data on the client. GraphQL allows you to request __typename, a meta field, at any point in a query to get the name of the object type at that point.
{
search (search: "an") {
__typename
... on Person {
name
height
birth_year
}
... on Vehicle {
name
model
}
... on Starship {
name
passengers
}
}
}

In the above query, the search returns a union type that can be one of three options. It would be impossible to tell apart the different types from the client without the __typename field

GraphQL services provide a few meta fields, the rest of which are used to expose the Introspection system.
. . .
In the next tutorial, we will look into the popular libraries that implement the GraphQL server specification.


On a mission to build Next-Gen Community Platform for Developers