If you’re building an application that uses React and GraphQL, then the Apollo Client library provides useful hooks that help manage the flow of your application’s data. A popular use-case of Apollo Client is the useQuery
hook, which makes a GraphQL query when a React component renders. However, many applications require the ability to fire a GraphQL query when an event occurs (such as a button click), rather than a component render. For this situation, look no further than Apollo Client’s useLazyQuery
hook.
useLazyQuery vs. useQuery
Unlike useQuery
, useLazyQuery
does not immediately execute its associated query upon component render. Rather, the hook returns a 2-tuple. The tuple contains a function that can be called in an event callback, and a result object, respectfully. The result object is similar to that returned by useQuery
. If you’ve never used Apollo Client, that result object will contain the following properties (among others):
loading: boolean
(Checks if the query resolution is currently in progress)error: ApolloError | undefined
(Provides information if the query resolution failed)data: any
(Provides an object in the shape of the query definition)
An Example: Dog vs. Cat Picture
Furthermore, useLazyQuery
comes in handy if you don’t know what your arguments will be upon component render. Let’s go through an example that demonstrates this situation. Suppose we have a basic user interface that displays a picture of a dog or cat depending on a user’s button click.
import React from 'react';
const App: React.FC<{}> = () => {
return (
<>
<img src={/* TODO - get from GraphQL */ undefined} />
<button>
Dog!
</button>
<button>
Cat!
</button>
</>
);
}
Additionally, suppose that we’ve written a GraphQL query and resolver that takes a simple string argument and returns a corresponding image based on whether the input reads “Dog” or “Cat.”
const GET_PET_PHOTO = gql`
query GetPetPhoto($choice: String!) {
pet(choice: $choice) {
id
imageURL
}
}
`;
Finally, leveraging useLazyQuery
and the above GraphQL query, we’re able to finish writing the component. getPet
is the function called in each button’s event callback. And, { loading, error, data }
represents a destructured version of the result object that changes based on the state of the query.
import React from 'react';
import { useLazyQuery } from '@apollo/client';
const App: React.FC<{}> = () => {
const [getPet, { loading, error, data }] = useLazyQuery(GET_PET_PHOTO);
if (loading) return <p>Loading ...</p>;
if (error) return `Error: ${error.message}`;
return (
<>
{data?.pet && <img src={data.pet.imageURL} />}
<button onClick={() => getPet({ variables: { choice: ‘Dog’ } })}>
Dog!
</button>
<button onClick={() => getPet({ variables: { choice: ‘Cat’ } })}>
Cat!
</button>
</>
);
}
Fire an Event-Driven GraphQL Query with Apollo Client for React
That’s it! The query function can be called by any callback in your React application. For more information on Apollo Client, feel free to explore the documentation here.