iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Queries

A query reads data; mutations write. Queries are POST /graphql requests with a query string + optional variables. Servers return only the fields you asked for — no over- or under-fetching.

Query syntax + client patterns

EXAMPLE
# 1) Basic shape
query {
    me {
        id
        name
        email
    }
}

# 2) Arguments
query {
    user(id: "u_42") {
        name
        email
    }
}

# 3) Variables — never inline user input
query GetUser($id: ID!) {
    user(id: $id) {
        name
        email
    }
}
# variables: { "id": "u_42" }

# 4) Multiple roots in one request
query Dashboard($userId: ID!) {
    me               { name }
    user(id: $userId) { posts(first: 5) { title } }
    feed(first: 10)  { id title }
}

# 5) Aliases — same field twice with different args
query {
    current: user(id: "me")     { name }
    other:   user(id: "u_42")   { name }
}

# 6) Fragments — reusable selection sets
fragment UserCard on User {
    id
    name
    avatarUrl
}

query {
    me            { ...UserCard }
    friends       { ...UserCard }
}

# 7) Directives — @include / @skip
query UserProfile($id: ID!, $withPosts: Boolean!) {
    user(id: $id) {
        name
        posts @include(if: $withPosts) { title }
    }
}

# 8) Pagination — cursor-based (Relay style)
query Feed($after: String) {
    feed(first: 20, after: $after) {
        edges {
            cursor
            node { id title }
        }
        pageInfo { hasNextPage endCursor }
    }
}

# --- Client side (JS, fetch) ---
const body = JSON.stringify({
    query: `query($id: ID!) { user(id: $id) { name email } }`,
    variables: { id: 'u_42' },
    operationName: 'GetUser',
});
const r = await fetch('/graphql', {
    method:  'POST',
    headers: { 'content-type': 'application/json' },
    body,
});
const { data, errors } = await r.json();
if (errors) throw errors;

# --- urql / Apollo / TanStack Query handle this for you ---
import { useQuery, gql } from '@apollo/client';

const GET_USER = gql`
    query GetUser($id: ID!) {
        user(id: $id) {
            name
            email
        }
    }
`;

function Profile({ id }) {
    const { loading, error, data } = useQuery(GET_USER, { variables: { id } });
    if (loading) return <Spinner />;
    if (error)   return <ErrorBox error={error} />;
    return <h1>{data.user.name}</h1>;
}

Why it matters

Use named operations + variables, never string-concatenated queries. Servers log operation names, dashboards group by them, and you get caching keyed off the name + variables for free.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
query GetUser($id: ID!) {
    user(id: $id) { id name email }
}
Try it Yourself »

Exercise

Top-level read entry point is…

type { user(id: ID!): User }

Test yourself

Q1. Pass a variable to a query named $id with…
Q2. Re-use a field selection across queries with…
Q3. Get two different fields under different names with…

Discussion

Loading…