Labs ICT
Pro Login

Writing Client Queries

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.