Episode 8 of 9
Mutations (Adding & Deleting Data)
Learn how to modify data with GraphQL mutations — adding new records and deleting existing ones.
Mutations — Adding & Deleting Data
So far we've only been reading data with queries. Mutations allow us to create, update, and delete data. Let's learn how!
What Are Mutations?
Mutations are GraphQL's way of modifying data on the server. They work just like queries but are used for write operations. By convention, they're defined under the Mutation type in your schema.
Defining Mutations in the Schema
First, we need an input type for structured input and mutation definitions:
type Mutation {
addGame(game: AddGameInput!): Game
deleteGame(id: ID!): [Game]
}
input AddGameInput {
title: String!
platform: [String!]!
}
Why Input Types?
Input types (input) are separate from regular types (type) because:
- They can only contain scalar fields and other input types
- They keep mutation arguments organized
- You often don't want to include fields like
id(auto-generated) or computed fields
Writing Mutation Resolvers
Add Game
import { v4 as uuidv4 } from 'uuid';
const resolvers = {
// ... Query resolvers ...
Mutation: {
addGame(_, args) {
const newGame = {
id: uuidv4(), // Generate a unique ID
...args.game, // Spread the input fields
};
games.push(newGame); // Add to our data store
return newGame; // Return the new game
},
},
};
Delete Game
const resolvers = {
Mutation: {
addGame(_, args) {
const newGame = { id: uuidv4(), ...args.game };
games.push(newGame);
return newGame;
},
deleteGame(_, args) {
games = games.filter(g => g.id !== args.id);
return games; // Return the remaining games
},
},
};
Running Mutations
Adding a Game
mutation AddGame($game: AddGameInput!) {
addGame(game: $game) {
id
title
platform
}
}
Variables:
{
"game": {
"title": "Hogwarts Legacy",
"platform": ["PS5", "Xbox", "PC"]
}
}
Response:
{
"data": {
"addGame": {
"id": "a1b2c3d4-...",
"title": "Hogwarts Legacy",
"platform": ["PS5", "Xbox", "PC"]
}
}
}
Deleting a Game
mutation DeleteGame($id: ID!) {
deleteGame(id: $id) {
id
title
}
}
{
"id": "1"
}
Mutation Best Practices
- Always return data — return the created/modified object so the client can update its cache
- Use input types — keep mutation arguments organized with
inputtypes - Validate inputs — check data before modifying your store
- Handle errors gracefully — throw meaningful errors for invalid operations
Adding a Delete Review and Delete Author
Extend your mutations to handle all types:
type Mutation {
addGame(game: AddGameInput!): Game
deleteGame(id: ID!): [Game]
addReview(review: AddReviewInput!): Review
deleteReview(id: ID!): [Review]
}
input AddReviewInput {
rating: Int!
content: String!
game_id: ID!
author_id: ID!
}
Key Takeaways
- Mutations are used for create, update, and delete operations
- Use
inputtypes for structured mutation arguments - Mutation resolvers modify data and return the result
- Always return useful data from mutations for client cache updates
- The mutation syntax is similar to queries but uses the
mutationkeyword
Next episode: Update Mutation — modifying existing data!