Skip to main content

Chapter 2: GraphQL Core Concepts

In this chapter, we explore the fundamental building blocks of GraphQL: schemas, types, queries, mutations, fragments, and directives. You’ll learn how these pieces work together to form a powerful API.


1. GraphQL Schema

A schema defines the shape of your API. It includes:

  • Object types (e.g., User, Post)
  • Query and Mutation root types
  • Fields with return types and arguments

Example Schema

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

type Query {
# Fetch a single user by ID
user(id: ID!): User

# List all users
users: [User!]!
}

input CreateUserInput {
name: String!
email: String!
}

type Mutation {
# Create a new user
createUser(input: CreateUserInput!): User!
}

2. Queries

2.1 Basic Query

query {
users {
id
name
email
}
}

Variables

Use variables to make queries dynamic:

query GetUserById($userId: ID!) {
user(id: $userId) {
id
name
email
}
}

With variables payload:

{
"userId": "123"
}

3. Mutations

Mutations modify data. They follow the same structure as queries:

mutation CreateNewUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
}
}

Variables:

{
"input": {
"name": "Alice",
"email": "alice@example.com"
}
}

4. Scalar and Custom Types

Built-in Scalars

  • Int, Float, String, Boolean, ID

Custom Scalar Example

Define a DateTime scalar to handle ISO strings:

scalar DateTime

type Event {
id: ID!
title: String!
startTime: DateTime!
}

In Yoga you can implement custom scalars:

import { GraphQLScalarType, Kind } from 'graphql';

const DateTimeScalar = new GraphQLScalarType({
name: 'DateTime',
description: 'ISO-8601 date string',
serialize(value) {
return value.toISOString();
},
parseValue(value) {
return new Date(value);
},
parseLiteral(ast) {
if (ast.kind === Kind.STRING) {
return new Date(ast.value);
}
return null;
},
});

5. Fragments

Fragments let you reuse field selections:

fragment UserFields on User {
id
name
email
}

query {
users {
...UserFields
}

user(id: "123") {
...UserFields
}
}

6. Aliases and Directives

Aliases

Fetch the same field with different arguments:

query {
alice: user(id: "1") {
name
}
bob: user(id: "2") {
name
}
}

Directives

@skip and @include control execution:

query GetUser($withEmail: Boolean!) {
user(id: "1") {
id
name
email @include(if: $withEmail)
}
}

7. Introspection

GraphQL supports querying its own schema:

{
__schema {
types {
name
kind
}
}
}

Use tools like GraphQL Playground to explore your API dynamically.


8. Execution Flow

  1. Parse: Convert query string to AST.
  2. Validate: Ensure query adheres to schema.
  3. Execute: Invoke resolvers to fetch data.
  4. Respond: Return JSON results.

✅ Summary

You’ve now covered the core concepts:

  • Defining schemas, object types, inputs
  • Writing queries and mutations with variables
  • Using fragments, aliases, and directives
  • Implementing custom scalars
  • Introspection and execution flow

Next, we’ll design robust schemas for real-world applications in Chapter 3: Schema Design.