Bird
Raised Fist0
GraphQLquery~5 mins

useQuery hook in GraphQL

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction

The useQuery hook helps you get data from a GraphQL server easily inside your app. It runs a query and gives you the results to use.

When you want to show a list of items from a server, like products or users.
When you need to get details about something, like a user profile or a post.
When you want to update your app automatically if the data changes on the server.
When you want to handle loading and error states while waiting for data.
When you want to fetch data once and use it in your React component.
Syntax
GraphQL
const { data, loading, error } = useQuery(YOUR_GRAPHQL_QUERY, {
  variables: { /* your variables here */ },
  fetchPolicy: 'cache-first' // optional
});

useQuery returns an object with data, loading, and error.

You pass your GraphQL query and optional variables to useQuery.

Examples
This example fetches a list of users with their id and name.
GraphQL
import { useQuery, gql } from '@apollo/client';

const GET_USERS = gql`
  query GetUsers {
    users {
      id
      name
    }
  }
`;

const { data, loading, error } = useQuery(GET_USERS);
This example fetches one user by their id using variables.
GraphQL
const GET_USER_BY_ID = gql`
  query GetUserById($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

const { data, loading, error } = useQuery(GET_USER_BY_ID, {
  variables: { id: '123' }
});
This example forces the query to always fetch fresh data from the server, ignoring cache.
GraphQL
const { data, loading, error } = useQuery(GET_USERS, {
  fetchPolicy: 'network-only'
});
Sample Program

This React component uses useQuery to get a list of books from the server. It shows loading text while waiting, error if something goes wrong, and the list of books when ready.

GraphQL
import React from 'react';
import { useQuery, gql } from '@apollo/client';

const GET_BOOKS = gql`
  query GetBooks {
    books {
      id
      title
      author
    }
  }
`;

function BooksList() {
  const { data, loading, error } = useQuery(GET_BOOKS);

  if (loading) return <p>Loading books...</p>;
  if (error) return <p>Error loading books.</p>;

  return (
    <ul>
      {data.books.map(book => (
        <li key={book.id}>{book.title} by {book.author}</li>
      ))}
    </ul>
  );
}

export default BooksList;
OutputSuccess
Important Notes

Always check loading and error before using data to avoid crashes.

You can pass variables to your query to get specific data.

useQuery automatically updates your component when data changes.

Summary

useQuery runs a GraphQL query and gives you data, loading, and error states.

Use it to fetch data inside React components easily.

Remember to handle loading and error states for a good user experience.

Practice

(1/5)
1. What does the useQuery hook in GraphQL primarily do inside a React component?
easy
A. Fetches data from a GraphQL server and provides loading and error states
B. Updates data on the GraphQL server
C. Deletes data from the GraphQL server
D. Creates a new GraphQL schema

Solution

  1. Step 1: Understand the purpose of useQuery

    The useQuery hook is designed to run a GraphQL query and fetch data.
  2. Step 2: Recognize the states it provides

    It also provides loading and error states to manage UI feedback during data fetching.
  3. Final Answer:

    Fetches data from a GraphQL server and provides loading and error states -> Option A
  4. Quick Check:

    useQuery fetches data = A [OK]
Hint: useQuery fetches data and manages loading/error states [OK]
Common Mistakes:
  • Confusing useQuery with mutation hooks
  • Thinking useQuery updates or deletes data
  • Assuming useQuery creates schemas
2. Which of the following is the correct syntax to use the useQuery hook with a query named GET_USERS?
easy
A. useQuery(GET_USERS).then(response => ...);
B. const { data, loading, error } = useQuery(GET_USERS);
C. const data = useQuery(GET_USERS);
D. const { data, error } = useQuery(GET_USERS, loading);

Solution

  1. Step 1: Recall the useQuery return structure

    The useQuery hook returns an object with data, loading, and error properties.
  2. Step 2: Match the correct destructuring syntax

    const { data, loading, error } = useQuery(GET_USERS); correctly destructures these properties from the hook call.
  3. Final Answer:

    const { data, loading, error } = useQuery(GET_USERS); -> Option B
  4. Quick Check:

    Destructure data, loading, error = C [OK]
Hint: Destructure data, loading, error from useQuery call [OK]
Common Mistakes:
  • Not destructuring loading state
  • Using promises with useQuery (it's a hook)
  • Passing loading as argument
3. Given this code snippet:
const { data, loading, error } = useQuery(GET_POSTS);
if (loading) return 'Loading...';
if (error) return 'Error!';
return data.posts.length;

What will be the output if data.posts contains 5 posts?
medium
A. 5
B. 'Error!'
C. undefined
D. 'Loading...'

Solution

  1. Step 1: Check loading and error conditions

    The code returns 'Loading...' if loading is true and 'Error!' if error exists. Since data.posts has 5 posts, loading is false and error is null.
  2. Step 2: Return the length of posts array

    With no loading or error, the code returns data.posts.length, which is 5.
  3. Final Answer:

    5 -> Option A
  4. Quick Check:

    data.posts.length = 5 [OK]
Hint: Check loading/error first, then return data length [OK]
Common Mistakes:
  • Ignoring loading state and expecting data immediately
  • Confusing error with data
  • Returning undefined if data is not checked
4. Identify the error in this code using useQuery:
const { data, loading, error } = useQuery(GET_COMMENTS);
if (loading) return ;
if (error) return

Error occurred

;
return data.comments.map(c => <p>{c.text}</p>);
medium
A. The map function should use curly braces instead of parentheses
B. The component returns JSX before checking loading
C. The query name GET_COMMENTS is not imported
D. No error; code is correct

Solution

  1. Step 1: Check for common mistakes in useQuery usage

    The code uses GET_COMMENTS but does not show it being imported or defined, which is required.
  2. Step 2: Verify JSX and map usage

    The JSX and map syntax are correct; returning JSX conditionally is valid.
  3. Final Answer:

    The query name GET_COMMENTS is not imported -> Option C
  4. Quick Check:

    Missing query import = A [OK]
Hint: Always import your GraphQL queries before useQuery [OK]
Common Mistakes:
  • Forgetting to import the query
  • Returning JSX before loading check
  • Incorrect map syntax for JSX
5. You want to fetch a list of users but only display them after the data is fully loaded. Which pattern correctly uses useQuery to achieve this?
hard
A. const { data } = useQuery(GET_USERS); if (!loading) return data.users.map(u => u.name); else return 'Loading...';
B. const { loading } = useQuery(GET_USERS); if (loading) return data.users; else return 'Loading...';
C. const { data } = useQuery(GET_USERS); return data.users.map(u => u.name);
D. const { data, loading } = useQuery(GET_USERS); if (loading) return 'Loading...'; return data.users.map(u => u.name);

Solution

  1. Step 1: Understand loading state usage

    We must show 'Loading...' while data is loading, so check if loading is true first.
  2. Step 2: Return user list only after loading is false

    const { data, loading } = useQuery(GET_USERS); if (loading) return 'Loading...'; return data.users.map(u => u.name); correctly returns 'Loading...' if loading is true, else maps over data.users.
  3. Final Answer:

    const { data, loading } = useQuery(GET_USERS); if (loading) return 'Loading...'; return data.users.map(u => u.name); -> Option D
  4. Quick Check:

    Check loading first, then return data = B [OK]
Hint: Always check loading before accessing data [OK]
Common Mistakes:
  • Accessing data before loading is false
  • Returning data when loading is true
  • Ignoring loading state completely