Writing Client Queries
Now that you understand how GraphQL works on the server, let's look at how to write queries from the client side. We'll use Apollo Client, the most popular GraphQL client library.
Apollo Client makes it easy to fetch, cache, and manage GraphQL data in your applications.
Setting Up Apollo Client
First, install Apollo Client in your project:
npm install @apollo/client graphql
Then initialize it in your application:
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';
const client = new ApolloClient({
link: new HttpLink({ uri: 'http://localhost:4000/graphql' }),
cache: new InMemoryCache(),
});
The HttpLink tells Apollo where your GraphQL server is. The InMemoryCache stores query results for fast access.
Basic Queries with useQuery
In React, you use the useQuery hook to execute queries. It returns loading, error, and data states.
import { useQuery, gql } from '@apollo/client';
const GET_USERS = gql`
query GetUsers {
users {
id
name
email
}
}
`;
function UserList() {
const { loading, error, data } = useQuery(GET_USERS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{data.users.map(user => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
);
}
The gql tag parses your query string into a query document. useQuery handles the loading, error, and data states for you.
Query with Variables
Most queries need dynamic values. Use variables to pass parameters safely:
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
title
}
}
}
`;
function UserProfile({ userId }) {
const { loading, error, data } = useQuery(GET_USER, {
variables: { id: userId },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h2>{data.user.name}</h2>
<p>{data.user.email}</p>
<h3>Posts</h3>
<ul>
{data.user.posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
Variables are passed separately from the query string. This is safer than string interpolation and prevents injection attacks.
Query Options
Apollo Client provides many options to customize query behavior:
const { data } = useQuery(GET_USERS, {
// Skip the query under certain conditions
skip: !isLoggedIn,
// Refetch data at intervals
pollInterval: 30000, // Every 30 seconds
// Fetch policy controls caching
fetchPolicy: 'cache-and-network', // Use cache, but also network
// Error policy
errorPolicy: 'all', // Return partial data with errors
// On completed callback
onCompleted: (data) => {
console.log('Query completed:', data);
},
// On error callback
onError: (error) => {
console.error('Query failed:', error);
},
});
These options give you fine-grained control over when and how queries execute.