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

  1. Definition: Mutations are a type of operation in GraphQL that allows you to modify server-side data.
  2. Structure: Mutations have a similar structure to queries but typically include input arguments to specify the data to be modified.
  3. 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 takes name and age as input arguments and returns a User 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 takes args containing the input arguments (name and age).
  • 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.

mutation {
  addUser(name: "John Doe", age: 30) {
    id
    name
    age
  }
}

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.

  1. Schema Definition:

    type Mutation {
      updateUserAge(id: ID!, age: Int!): User
    }
    
  2. 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;
        },
      },
    };
    
  3. Test the Mutation:

    mutation {
      updateUserAge(id: 1, age: 35) {
        id
        name
        age
      }
    }
    

Solution

  1. Schema Definition:

    type Mutation {
      updateUserAge(id: ID!, age: Int!): User
    }
    
  2. 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;
        },
      },
    };
    
  3. 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.

© Copyright 2024. All rights reserved