Introduction

In GraphQL, input types are used to define the structure of the data that can be passed as arguments to queries and mutations. They are similar to object types but are specifically designed for input purposes. Input types help in validating and structuring the data that the client sends to the server.

Key Concepts

  1. Definition of Input Types

  • Input types are defined using the input keyword.
  • They are used to encapsulate multiple arguments into a single argument.
  • Input types cannot have fields that are other object types, only scalar types or other input types.

  1. Syntax

The syntax for defining an input type is similar to defining an object type but uses the input keyword.

input UserInput {
  name: String!
  age: Int
  email: String!
}

  1. Using Input Types in Mutations

Input types are commonly used in mutations to pass complex data structures.

type Mutation {
  createUser(input: UserInput!): User
}

  1. Example Mutation

Here is an example of how you might use an input type in a mutation:

mutation {
  createUser(input: {
    name: "John Doe",
    age: 30,
    email: "[email protected]"
  }) {
    id
    name
    email
  }
}

Practical Example

Step-by-Step Example

  1. Define the Input Type:

    input UserInput {
      name: String!
      age: Int
      email: String!
    }
    
  2. Define the Mutation:

    type Mutation {
      createUser(input: UserInput!): User
    }
    
  3. Define the User Type:

    type User {
      id: ID!
      name: String!
      age: Int
      email: String!
    }
    
  4. Resolver for the Mutation:

    const resolvers = {
      Mutation: {
        createUser: (parent, args, context, info) => {
          const { input } = args;
          // Simulate user creation
          const newUser = {
            id: Date.now().toString(),
            ...input
          };
          // Here you would typically save the user to a database
          return newUser;
        }
      }
    };
    

Complete Example

Here is a complete example including schema and resolver:

Schema Definition:

type User {
  id: ID!
  name: String!
  age: Int
  email: String!
}

input UserInput {
  name: String!
  age: Int
  email: String!
}

type Mutation {
  createUser(input: UserInput!): User
}

type Query {
  users: [User]
}

Resolver Implementation:

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    age: Int
    email: String!
  }

  input UserInput {
    name: String!
    age: Int
    email: String!
  }

  type Mutation {
    createUser(input: UserInput!): User
  }

  type Query {
    users: [User]
  }
`;

let users = [];

const resolvers = {
  Query: {
    users: () => users,
  },
  Mutation: {
    createUser: (parent, { input }) => {
      const newUser = {
        id: Date.now().toString(),
        ...input,
      };
      users.push(newUser);
      return newUser;
    },
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

Exercises

Exercise 1: Define and Use an Input Type

  1. Define an input type ProductInput with fields name, price, and description.
  2. Create a mutation addProduct that takes ProductInput as an argument and returns a Product type.
  3. Implement the resolver for addProduct.

Solution:

input ProductInput {
  name: String!
  price: Float!
  description: String
}

type Product {
  id: ID!
  name: String!
  price: Float!
  description: String
}

type Mutation {
  addProduct(input: ProductInput!): Product
}

Resolver:

const resolvers = {
  Mutation: {
    addProduct: (parent, { input }) => {
      const newProduct = {
        id: Date.now().toString(),
        ...input,
      };
      // Here you would typically save the product to a database
      return newProduct;
    },
  },
};

Exercise 2: Extend the User Input Type

  1. Add a new field address of type String to the UserInput type.
  2. Update the createUser mutation to handle the new address field.

Solution:

input UserInput {
  name: String!
  age: Int
  email: String!
  address: String
}

type Mutation {
  createUser(input: UserInput!): User
}

Resolver:

const resolvers = {
  Mutation: {
    createUser: (parent, { input }) => {
      const newUser = {
        id: Date.now().toString(),
        ...input,
      };
      // Here you would typically save the user to a database
      return newUser;
    },
  },
};

Conclusion

Input types in GraphQL are essential for structuring and validating the data sent from the client to the server. They simplify the process of passing complex data structures and ensure that the data adheres to the defined schema. By mastering input types, you can create more robust and maintainable GraphQL APIs.

© Copyright 2024. All rights reserved