Odyssey

Client-side GraphQL with React & Apollo
beta

Feature overview and setupGraphQL basicsApollo ExplorerApollo ClientCodegenDefining a queryArgumentsThe useQuery hook with variablesIntroducing mutationsOur mutation in action
9. Introducing mutations
4m

Overview

So far, we've only dealt with retrieving data from our API. Now it's time to switch gears and work on modifying our data.

Each track in our app displays the number of times it's been viewed. We want to increment this number every time a user visits the track page from the homepage. We'll do this using GraphQL mutations!

http://localhost:3000/track/c_0

The track page, highlighting the track's number of views we wish to increment

In this lesson, we will:

  • Learn what a mutation is
  • Test a mutation in Explorer

The Mutation type

So far, our app has only used one type of GraphQL operation: queries. These are read-only operations to retrieve data. To modify data, we need to use another type of GraphQL operation: mutations, which are write operations.

Much like the Query type, the Mutation type serves as an entry point to our schema. It follows the same syntax as the schema definition language, or SDL, that we've been using so far.

Schema syntax

In the schema of the GraphQL server, the Mutation type is declared using the type keyword, then the name Mutation. Inside the curly braces are the entry points: the fields we can use to mutate our data.

Illustration showing the schema syntax for adding a mutation

Mutations often start with a verb that describes the specific action of our update operation (such as add, delete, or create), followed by whatever data the mutation acts on. Because mutations typically modify a specific object, they often require arguments. The return type of the mutation comes after the colon.

The mutation response should include the data that the mutation updated, so that our client can update its UI without having to run a followup query to fetch those details!

We can take a closer look at our API's Mutation type by returning to the Schema page in Sandbox, and selecting Mutation from the left-hand menu.

http://studio.apollographql.com/sandbox/schema/reference

The Schema Reference page in Sandbox opened to the Mutation type

We can see that to increment the number of views on a specific track, this field takes that track's id as an argument. It returns a type called IncrementTrackViewsResponse. Let's click on that type to take a closer look.

http://studio.apollographql.com/sandbox/schema/reference

The Schema Reference page in Sandbox, opened to the IncrementTrackViewsReponse type

The fields on this type show us the data we'll be able to query when the mutation completes. We can see the code, success, and message that results from the operation, and we also get access to the entire Track object that was modified under the track field.

Working with mutations

To get going with this mutation, let's return to the Mutation page and scroll down to the incrementTrackViews field. To open this mutation in the Explorer, let's click on the play icon to the right of the field's description.

https://studio.apollographql.com/sandbox/schema/reference

Screenshot of the Mutation field, incrementTrackViews, with the play button highlighted

This takes us to the Explorer page, with the sidebar open and ready for us to start building our first mutation.

https://studio.apollographql.com/sandbox/explorer

Screenshot of Explorer with an empty Operation panel, ready for us to start building our query

Click the plus button (⊕) beside incrementTrackViews to add it to our Operation panel. This pre-fills some information for us!

mutation IncrementTrackViews($incrementTrackViewsId: ID!) {
incrementTrackViews(id: $incrementTrackViewsId) {
}
}

✍️ Building a GraphQL mutation

We start with the mutation keyword, and then the name of the operation (which the Explorer has named IncrementTrackViews for us). Inside the brackets, we've got a variable denoted by the $ symbol called incrementTrackViewsId, which is of type ID and required.

This variable is set in the Variables section below. Right now it's set to null, so let's change it to the same track ID we've been working with: c_0.

{
"incrementTrackViewsId": "c_0"
}
https://studio.apollographql.com/sandbox/explorer

Screenshot of Explorer with the mutation operated added, and a track Id variable filled in

Back to the mutation in the Operation panel!

Inside the curly braces is where we list our mutation entry point: incrementTrackViews. It takes in an id argument, which we set to the variable incrementTrackViewsId, the same one we just set to c_0.

Now inside the second pair of curly braces we can start to add the fields available in our response object. These fields are in the sidebar, making it really easy to build this mutation by clicking on the plus button (⊕) button beside the field.

We want to see the code, the success boolean, the message, and the track object itself.

Inside the track object, we want the id and the numberOfViews. The number of views is what we're updating, so we want to see the newly updated value after the mutation is hopefully successful. The id will be used by our Apollo Client cache, which we'll cover a little later when we get to the frontend implementation.

https://studio.apollographql.com/sandbox/explorer

The complete mutation operation built out in the Explorer

The mutation operation should look like this:

mutation IncrementTrackViews($incrementTrackViewsId: ID!) {
incrementTrackViews(id: $incrementTrackViewsId) {
code
success
message
track {
id
numberOfViews
}
}
}

Let's go ahead and run it!

On the right-hand side you can see the fields we expected: code is 200, the success flag is true, the message says it was successful and we get our newly updated track back.

https://studio.apollographql.com/sandbox/explorer

Screenshot of the Explorer showing a successful response to the IncrementTrackViews mutation

When we run the mutation again and again, we can see that the number of views is going up!

Let's see what happens when we change the incrementTrackViewsId to our silly string "DOESNTEXIST".

{
"incrementTrackViewsId": "DOESNTEXIST"
}

When we run this mutation, we see the response has code 404, success is false, and the message says Could not find track with specified ID. The track is also set to null with no data available.

https://studio.apollographql.com/sandbox/explorer

Screenshot of the Explorer showing a 404 response to the IncrementTrackViews mutation

Our mutation looks great and it's doing what it's supposed to! It's time to bring this functionality into our app.

Practice

Mutations vs Queries
Queries and mutations are both types of GraphQL
 
. Queries are 
 
operations that always 
 
 data. Mutations are
 
 operations that always 
 
data. Similar to Query fields, fields of the 
 
 type are also 
 
 into a GraphQL API.

Drag items from this box to the blanks above

  • operations

  • Mutation

  • assignments

  • write

  • create

  • retrieve

  • entry points

  • search

  • endpoints

  • read

  • delete

  • modify

To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
When writing a GraphQL mutation, which keyword should it start with?

Key takeaways

  • Mutations are write-operations that let us change data.
  • Like the Query type, the Mutation type acts as an entrypoint to our schema.

Up next

Our mutation is built and running as we expect. Now for the final step: bringing it into our client-side code, and seeing our changes reflected in the UI!

Previous
Next

Share your questions and comments about this lesson

This course is currently in

beta
. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              schema definition language

              GraphQL's schema definition language (SDL). The syntax for writing GraphQL schemas. All GraphQL APIs can use SDL to represent their schema, regardless of the API's programming language.

              SDL

              GraphQL's schema definition language (SDL). The syntax for writing GraphQL schemas. All GraphQL APIs can use SDL to represent their schema, regardless of the API's programming language.

              GraphQL server

              A server that contains a GraphQL schema and can resolve client-requested operations that are executed against that schema.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              Mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              arguments

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              variable

              A placeholder for dynamic values in an operation allowing parameterization and reusability in requests. Variables can be used to fill arguments or passed to directives.

              query GetUser($userId: ID!) {
              user(id: $userId) {
              firstName
              }
              }

              In the query above, userId is a variable. The variable and its type are declared in the operation signature, signified by a $. The type of variable is a non-nullable ID. A variable's type must match the type of any argument it's used for.

              variable

              A placeholder for dynamic values in an operation allowing parameterization and reusability in requests. Variables can be used to fill arguments or passed to directives.

              query GetUser($userId: ID!) {
              user(id: $userId) {
              firstName
              }
              }

              In the query above, userId is a variable. The variable and its type are declared in the operation signature, signified by a $. The type of variable is a non-nullable ID. A variable's type must match the type of any argument it's used for.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              argument

              A key-value pair associated with a particular schema field that lets operations pass data to that field's resolver.

              Argument values can be hardcoded as literal values (shown below for clarity) or provided via GraphQL variables (recommended).

              query GetHuman {
              human(id: "200") {
              name
              height(unit: "meters")
              }
              }
              variable

              A placeholder for dynamic values in an operation allowing parameterization and reusability in requests. Variables can be used to fill arguments or passed to directives.

              query GetUser($userId: ID!) {
              user(id: $userId) {
              firstName
              }
              }

              In the query above, userId is a variable. The variable and its type are declared in the operation signature, signified by a $. The type of variable is a non-nullable ID. A variable's type must match the type of any argument it's used for.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              Apollo Client

              An open-source library for client-side state management and GraphQL operation handling in Javascript/Typescript. Apollo Client is a fully featured caching GraphQL client with integrations for React, Angular, and more.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              Mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              operations

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              mutation

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              NEW COURSE ALERT

              Introducing Apollo Connectors

              Connectors are the new and easy way to get started with GraphQL, using existing REST APIs.

              Say goodbye to GraphQL servers and resolvers—now, everything happens in the schema!

              Take the course