Executing GraphQL Queries with useQuery0%

Executing GraphQL Queries with useQuery

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Executing GraphQL Queries with useQuery

The useQuery React hook is the primary mechanism for fetching GraphQL data in Apollo Client applications. It manages the complete query lifecycle—including loading states, error boundaries, data caching, background polling, and refetching—while integrating with TypeScript for end-to-end type safety.


1. Defining Typed Queries with gql

GraphQL documents are parsed using the gql tagged template literal:

TSX
import { gql } from "@apollo/client";
 
export const GET_PROJECT_DETAILS = gql`
query GetProjectDetails($projectId: ID!) {
project(id: $projectId) {
id
title
status
budget
teamLead {
id
name
avatarUrl
}
tasks(limit: 10) {
id
title
completed
}
}
}
`;

2. Using useQuery in a Component

TSX
import React from "react";
import { useQuery } from "@apollo/client";
import { GET_PROJECT_DETAILS } from "./queries";
 
interface Task {
id: string;
title: string;
completed: boolean;
}
 
interface ProjectData {
project: {
id: string;
title: string;
status: "ACTIVE" | "ARCHIVED" | "PENDING";
budget: number;
teamLead: {
name: string;
avatarUrl: string;
};
tasks: Task[];
};
}
 
interface ProjectVars {
projectId: string;
}
 
export function ProjectDetailView({ projectId }: { projectId: string }) {
const { data, loading, error, refetch, networkStatus } = useQuery<ProjectData, ProjectVars>(
GET_PROJECT_DETAILS,
{
variables: { projectId },
fetchPolicy: "cache-and-network", // Serves cached data instantly, updates from network in background
notifyOnNetworkStatusChange: true, // Enables tracking refetch spinners
}
);
 
if (loading && !data) {
return (
<div className="p-8 text-cyan-400 flex items-center gap-2">
<span className="h-4 w-4 animate-spin rounded-full border-2 border-cyan-400 border-t-transparent" />
Loading project telemetry...
</div>
);
}
 
if (error) {
return (
<div className="p-6 bg-rose-950/40 border border-rose-800 rounded-xl text-rose-300">
<h3 className="font-bold">Error loading project</h3>
<p className="text-xs mt-1">{error.message}</p>
<button
onClick={() => refetch()}
className="mt-3 px-3 py-1 bg-rose-800 hover:bg-rose-700 text-white rounded text-xs font-semibold"
>
Retry Query
</button>
</div>
);
}
 
const { project } = data!;
 
return (
<div className="p-8 bg-slate-900 text-white rounded-xl border border-slate-800">
<div className="flex justify-between items-start mb-6">
<div>
<h1 className="text-2xl font-bold">{project.title}</h1>
<span className="inline-block mt-1 px-2.5 py-0.5 rounded-full text-xs font-mono bg-cyan-950 text-cyan-400 border border-cyan-800">
Status: {project.status}
</span>
</div>
 
<button
onClick={() => refetch()}
className="px-3 py-1.5 bg-slate-800 hover:bg-slate-700 rounded text-xs font-medium text-slate-300"
>
Refresh Data
</button>
</div>
 
<div className="border-t border-slate-800 pt-4 space-y-2">
<h2 className="text-sm font-semibold text-slate-400">Milestone Tasks</h2>
{project.tasks.map((task) => (
<div key={task.id} className="flex items-center gap-3 p-2 bg-slate-950 rounded text-xs">
<span className={task.completed ? "text-emerald-400 line-through" : "text-slate-200"}>
{task.title}
</span>
</div>
))}
</div>
</div>
);
}

3. Understanding Fetch Policies

The fetchPolicy option controls how Apollo resolves data between the client cache and the network:

Fetch PolicyBehaviorBest Use Case
cache-first (Default)Checks cache; if found, never hits network. Hits network only on cache miss.Static or rarely changing reference data.
cache-and-networkReturns cached data immediately, then fetches from network in background and updates UI.High-activity dashboards requiring instant loads + fresh data.
network-onlyAlways queries the network, updating the cache with results.Critical financial balances or live checkout totals.
no-cacheAlways queries network and does not write to cache.Sensitive user data that should never persist in memory.

Interactive Quiz

Practice Quiz

Question 1
What does the fetchPolicy: "cache-and-network" setting accomplish?
Question 2
Why is notifyOnNetworkStatusChange: true necessary when using refetch()?
Question 3
How do you pass dynamic parameters into a GraphQL query with useQuery?
Question 4
What happens if a component using useQuery unmounts before the network request resolves?
Question 5
What is the benefit of defining TypeScript interfaces for ProjectData and ProjectVars?
Next Lesson

GraphQL Mutations and Optimistic UI Updates

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext