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!
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.
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.
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.
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.
This takes us to the Explorer page, with the sidebar open and ready for us to start building our first mutation.
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"}
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.
The mutation operation should look like this:
mutation IncrementTrackViews($incrementTrackViewsId: ID!) {incrementTrackViews(id: $incrementTrackViewsId) {codesuccessmessagetrack {idnumberOfViews}}}
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.
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.
Our mutation looks great and it's doing what it's supposed to! It's time to bring this functionality into our app.
Practice
Query
fields, fields of the Drag items from this box to the blanks above
assignments
entry points
Mutation
endpoints
search
operations
delete
read
write
create
retrieve
modify
Key takeaways
- Mutations are write-operations that let us change data.
- Like the
Query
type, theMutation
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!
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.