Docs
Launch GraphOS Studio

Mutations


In addition to fetching data using queries, also handles . Mutations are identical to queries in syntax, the only difference being that you use the keyword mutation instead of query to indicate that the root on this are going to be performing writes to the backend.

For more information on , we recommend reading this guide.

represent two things in one :

  1. The name with , which represents the actual to be done on the server.
  2. The you want back from the result of the to update the client.

All business logic involved in mutating data is handled by the server. The client has no direct knowledge of how data will be mutated. Just like any other , each in a schema returns a type. If that type is an , you may fields on that type, which can be used to fetch the new state of the mutated object.

In this example, we define a called UpvotePost, which performs the schema's upvotePost(postId:) .

mutation UpvotePost($postId: Int!) {
upvotePost(postId: $postId) {
id
votes
}
}

The server implements the upvotePost(postId:) to add an upvote to the post with the given postId and return that post. The above selects the id and votes on the returned Post object.

The result might be:

{
"data": {
"upvotePost": {
"id": "123",
"votes": 5
}
}
}

Performing mutations

Similar to queries, are represented by instances of generated classes, conforming to the GraphQLMutation protocol. are generated used to define . For more information on passing arguments to a mutation see "Operation arguments"

You pass a object to ApolloClient.perform(mutation:) to send the to the server, execute it, and receive typed results.

apollo.perform(mutation: UpvotePostMutation(postId: postId)) { result in
guard let data = try? result.get().data else { return }
print(data.upvotePost?.votes)
}

Using fragments in mutation results

In many cases, you'll want to use results to update your UI. can be a great way of sharing result handling between queries and mutations:

mutation UpvotePost($postId: Int!) {
upvotePost(postId: $postId) {
...PostDetails
}
}
client.perform(mutation: UpvotePostMutation(postId: postId)) { result in
guard let data = try? result.get().data else { return }
self.configure(with: data.upvotePost?.fragments.postDetails)
}

Passing input objects

The includes input objects as a way to pass complex values to . Input objects are often defined as , because they give you a compact way to pass in objects to be created:

mutation CreateReviewForEpisode($episode: Episode!, $review: ReviewInput!) {
createReview(episode: $episode, review: $review) {
stars
commentary
}
}
let review = ReviewInput(stars: 5, commentary: "This is a great movie!")
apollo.perform(mutation: CreateReviewForEpisodeMutation(episode: .jedi, review: review))

Designing mutation results

When people talk about , they often focus on the data fetching side of things, because that's where GraphQL brings the most value. can be pretty nice if done well, but the principles of designing good mutations, and especially good mutation result types, are not yet well-understood in the open source community. So when you are working with mutations it might often feel like you need to make a lot of application-specific decisions.

In , can return any type, and that type can be queried just like a regular GraphQL . So the question is - what type should a particular mutation return?

In most cases, the data available from a result should be the server developer's best guess of the data a client would need to understand what happened on the server. For example, a mutation that creates a new comment on a blog post might return the comment itself. A mutation that reorders an array might need to return the whole array.

Previous
Queries
Next
Subscriptions
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company