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
- Parse: Convert query string to AST.
- Validate: Ensure query adheres to schema.
- Execute: Invoke resolvers to fetch data.
- 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.