Categories
GraphQL JavaScript

Introduction to GraphQL — Variables and Complex Operations

Spread the love

GraphQL is a query language for our API and a server-side runtime for running queries by using a type system for our data.

In this article, we’ll look at more complex GraphQL operations, including passing in variables, directives, mutations, and more.

Variables

In most apps, the arguments for queries need to be dynamic. It wouldn’t be a good idea to pass in dynamic arguments directly to the query string.

Fortunately, GraphQL lets us pass in variables into our operations request.

For example, we can write:

query PersonName($id: Int) {  
  person(id: $id) {  
    name  
  }  
}

to pass in an $id variable into our person query.

Then we can pass in variables via an object to make the request:

{  
  "id": 1000  
}

Then we get something like:

{  
  "data": {  
    "person": {  
      "name": "Jane"  
    }  
  }  
}

as the response.

Variable definitions

Variable definitions start with the variable name prefixed with a $, then the type of the variable.

In the example above, we have $id as the variable name and Int as the type.

All declared variables must be either a scalar, enums or other input object types.

If we want to pass a complex object into a field, we need to know the input type to match on the server.

Default variables

We can set default values for variables as follows:

query PersonName($id: Int = 1) {  
  person(id: $id) {  
    name  
  }  
}

In the code above, we added = 1 after $id: Int to set the default value for $id to 1.

Directives

We can use directives to dynamically change the structure and shape of our queries using variables.

For example, we can include directives as follows to make our query dynamic:

query Person($id: Int, $withFriends: Boolean!) {  
  person(id: $id) {  
    name  
    friends @include(if: $withFriends) {  
      name  
    }  
  }  
}

In the code above, we have the @include(if: $withFriends) directive to conditionally includes friends if $withFriends is true.

Therefore, if we make the following query with the following variables:

{  
  "id": 1000,  
  "withFriends": false  
}

Then we may get something like:

{  
  "data": {  
    "person": {  
      "name": "Jane"  
    }  
  }  
}

as a response.

A directive can be attached to a field or fragment inclusion and can affect the execution of the query in any way the server desires.

The core GraphQL specification includes 2 directives that must be supported by any spec-compliant GraphQL server implementation:

  • @include(if: Boolean) — only include this field if the argument if true.
  • @skip(if: Boolean) — skip this field if the argument is true.

It helps us get out of situations where we would have to do string manipulating to add and remove fields in our query.

Mutations

We can use mutations to send requests to change data on the server.

They’re similar to queries, except that it starts with the keyword mutation instead.

For example, we can define a mutation as follows:

mutation CreatePerson($firstName: String, $lastName: String) {  
  createPerson(firstName: $firstName, lastName: $lastName) {  
    firstName  
    lastName  
  }  
}

Then if we make the following query:

{  
  "firstName": "Joe",  
  "lastName": "Smith"  
}

we may get the following response:

{  
  "data": {  
    "createPerson": {  
      "firstName": "Joe",  
      "lastName": "Smith"  
    }  
  }  
}

In the response, we return the firstName and lastName fields as we specified in the request.

A mutation can contain multiple fields like a query. Mutations fields run in series.

This means that if we sent 2 createPerson mutations in one request. The first will finish before the second begins.

Inline Fragments

We can define interface and union types with GraphQL requests.

To do this, we use inline fragments to access data on the underlying concrete type.

For example, we can write the following query:

query Thing($id: Int!) {  
  person(id: $id) {  
    name  
    ... on Person{  
      gender  
    }  
    ... on Robot{  
      memory  
    }  
  }  
}

In the query above, the ...on operator indicates that we include an inline fragment within our query, where Person and Robot are our fragments.

Named fragments can also be inline fragments since they have a type attached.

Meta fields

We can request a __typename field to get the type of data returned in the response.

For example, if we have the following query:

{  
  search(text: "an") {  
    __typename  
    ... on Human {  
      name  
    }  
    ... on Robot {  
      name  
    }  
  }  
}

Then we may get the following response from the server:

{  
  "data": {  
    "search": [  
      {  
        "__typename": "Human",  
        "name": "Hans"  
      },  
      {  
        "__typename": "Robot",  
        "name": "Jane"  
      }  
    ]  
  }  
}

Conclusion

We can define mutations to make requests to change data.

To make requests dynamic, we can use variables to include variable data and directives for conditional inclusion of data in our response.

We can also use inline fragments for union types and include the type of data returned in the response by including the __typename property.

Leave a Reply

Your email address will not be published. Required fields are marked *