🖋 GraphQL operations
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
We declare the
Mutation type using the
type keyword, then the name
Mutation. Inside the curly braces, we have our entry points, the fields we'll be using to mutate our data.
We recommend starting with a verb that describes the specific action of our update operation (such as
create), followed by whatever data the mutation acts on. Because mutations typically modify a specific object, they often require arguments. We can add arguments as needed, following the same SDL syntax. The return type of the mutation comes after the colon.
For the mutation response, we should return the data that the mutation updated, so that our client can update its UI without having to run a followup query.
Which of these are good names for mutations based on the recommended conventions above?
🤔 Modifying multiple objects
When a mutation updates more than just one object, how do we pick which one to return?
To answer that question, let's look at an example schema with spacecats and missions.
A spacecat has a list of missions they've been assigned to. A mission can also have more than one spacecat assigned to it, like a crew. We want to create a mutation called
assignMission that assigns one spacecat to a particular mission. This would update that spacecat's list of missions, and it would also update a mission's list of crew members.
So which type should our mutation return?
We'll want to return both, because our client might need both.
In addition, we'll need to account for any partial errors that might occur and return helpful information to the client. We recommend adding 3 common fields to all mutation responses:
Intthat refers to the status of the response, similar to an HTTP status code.
Booleanflag that indicates whether all the updates the mutation was responsible for succeeded.
Stringto display information about the result of the mutation on the client side. This is particularly useful if the mutation was only partially successful and a generic error message can't tell the whole story.
Which of these are reasons to create a separate object for a mutation's return type?
Circling back to the
assignMission mutation, we're going to create a new type specifically for its response. By convention, this return type will start with the name of the mutation (
AssignMission) and end with
Response. This type will contain the three informational properties, as well as additional fields for each object that the mutation updated.
That's the basics of what we need to know about mutations! Let's dive into the code and add our first mutation to the schema.