In this section, we will delve into GraphQL mutations, which are used to modify data on the server. Mutations are similar to queries in GraphQL, but they allow you to perform operations that change the state of the data, such as creating, updating, or deleting records.
Key Concepts
- Definition: Mutations are a type of operation in GraphQL that allows you to modify server-side data.
- Structure: Mutations have a similar structure to queries but typically include input arguments to specify the data to be modified.
- Resolvers: Each mutation must have a corresponding resolver function that handles the logic for modifying the data.
Basic Mutation Structure
A mutation in GraphQL is defined in the schema and includes the following components:
- Mutation Type: Defines the available mutation operations.
- Input Arguments: Specifies the data required to perform the mutation.
- Return Type: Defines the type of data returned after the mutation is executed.
Example Schema Definition
type Mutation { addUser(name: String!, age: Int!): User } type User { id: ID! name: String! age: Int! }
In this example:
addUser
is a mutation that takesname
andage
as input arguments and returns aUser
type.
Example Resolver
const resolvers = { Mutation: { addUser: (parent, args, context, info) => { const newUser = { id: generateUniqueId(), name: args.name, age: args.age, }; // Logic to save the new user to the database users.push(newUser); return newUser; }, }, };
In this resolver:
addUser
function takesargs
containing the input arguments (name
andage
).- A new user object is created and added to the
users
array. - The newly created user is returned.
Practical Example
Let's create a simple GraphQL server with a mutation to add a user.
Step 1: Setting Up the Server
First, set up a basic GraphQL server using express
and apollo-server-express
.
const express = require('express'); const { ApolloServer, gql } = require('apollo-server-express'); const app = express(); const port = 4000; const typeDefs = gql` type User { id: ID! name: String! age: Int! } type Mutation { addUser(name: String!, age: Int!): User } type Query { users: [User] } `; let users = []; const resolvers = { Query: { users: () => users, }, Mutation: { addUser: (parent, args) => { const newUser = { id: users.length + 1, name: args.name, age: args.age, }; users.push(newUser); return newUser; }, }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.applyMiddleware({ app }); app.listen(port, () => { console.log(`Server is running at http://localhost:${port}${server.graphqlPath}`); });
Step 2: Testing the Mutation
You can test the mutation using GraphiQL or any other GraphQL client.
This mutation will add a new user with the name "John Doe" and age 30 to the server.
Exercises
Exercise 1: Add a New Mutation
Task: Add a mutation to update a user's age.
-
Schema Definition:
type Mutation { updateUserAge(id: ID!, age: Int!): User }
-
Resolver:
const resolvers = { Mutation: { updateUserAge: (parent, args) => { const user = users.find(user => user.id === args.id); if (!user) { throw new Error('User not found'); } user.age = args.age; return user; }, }, };
-
Test the Mutation:
mutation { updateUserAge(id: 1, age: 35) { id name age } }
Solution
-
Schema Definition:
type Mutation { updateUserAge(id: ID!, age: Int!): User }
-
Resolver:
const resolvers = { Mutation: { updateUserAge: (parent, args) => { const user = users.find(user => user.id === args.id); if (!user) { throw new Error('User not found'); } user.age = args.age; return user; }, }, };
-
Test the Mutation:
mutation { updateUserAge(id: 1, age: 35) { id name age } }
Common Mistakes and Tips
- Missing Input Arguments: Ensure that all required input arguments are provided when calling a mutation.
- Error Handling: Always handle errors gracefully in your resolvers to provide meaningful feedback to the client.
- Validation: Validate input data to prevent invalid data from being processed.
Conclusion
In this section, we covered the basics of GraphQL mutations, including their structure, how to define them in the schema, and how to implement resolvers. We also provided a practical example and exercises to reinforce the concepts. Understanding mutations is crucial for performing data modifications in a GraphQL server, and mastering them will enable you to build more dynamic and interactive applications.