Core hooks for executing GraphQL queries with automatic state management, caching, and loading indicators.
Execute GraphQL queries and manage loading, error, and data states automatically.
/**
* Execute a GraphQL query and return the result with loading/error states
* @param query - GraphQL query document
* @param options - Configuration options for the query
* @returns Query result with data, loading, error states and utility functions
*/
function useQuery<TData = any, TVariables = OperationVariables>(
query: DocumentNode,
options?: QueryHookOptions<TData, TVariables>
): QueryResult<TData, TVariables>;
interface QueryHookOptions<TData, TVariables> extends QueryOptions<TVariables, TData> {
/** Skip executing the query */
skip?: boolean;
/** Execute the query on every render */
fetchPolicy?: FetchPolicy;
/** Error policy for handling GraphQL errors */
errorPolicy?: ErrorPolicy;
/** Return partial data from cache */
returnPartialData?: boolean;
/** Polling interval in milliseconds */
pollInterval?: number;
/** Notify when network only fetchPolicy completes */
notifyOnNetworkStatusChange?: boolean;
/** Context passed to Apollo Link */
context?: DefaultContext;
/** Partial observer options */
partialRefetch?: boolean;
/** Client instance to use */
client?: ApolloClient<any>;
}
interface QueryResult<TData, TVariables> {
/** Query data */
data?: TData;
/** Loading state */
loading: boolean;
/** Error state */
error?: ApolloError;
/** Network status */
networkStatus: NetworkStatus;
/** Whether query has been called */
called: boolean;
/** Apollo Client instance */
client: ApolloClient<any>;
/** Refetch the query */
refetch: (variables?: Partial<TVariables>) => Promise<ApolloQueryResult<TData>>;
/** Fetch more data */
fetchMore: <K extends keyof TVariables>(
fetchMoreOptions: FetchMoreQueryOptions<TVariables, K> & FetchMoreOptions<TData, TVariables>
) => Promise<ApolloQueryResult<TData>>;
/** Start polling */
startPolling: (pollInterval: number) => void;
/** Stop polling */
stopPolling: () => void;
/** Subscribe to more data */
subscribeToMore: <TSubscriptionData, TSubscriptionVariables>(
options: SubscribeToMoreOptions<TData, TSubscriptionVariables, TSubscriptionData>
) => () => void;
/** Update query result */
updateQuery: (
mapFn: (previousQueryResult: TData, options: UpdateQueryOptions<TVariables>) => TData
) => void;
}Usage Examples:
import { useQuery, gql } from "@apollo/react-hooks";
const GET_USERS = gql`
query GetUsers($limit: Int) {
users(limit: $limit) {
id
name
email
}
}
`;
function UsersList() {
const { loading, error, data, refetch } = useQuery(GET_USERS, {
variables: { limit: 10 },
fetchPolicy: "cache-first",
pollInterval: 5000, // Poll every 5 seconds
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<button onClick={() => refetch()}>Refresh</button>
<ul>
{data?.users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}Create a query function that can be called on-demand rather than immediately on component mount.
/**
* Create a query function that can be called on-demand
* @param query - GraphQL query document
* @param options - Configuration options for the lazy query
* @returns Tuple with execute function and query result
*/
function useLazyQuery<TData = any, TVariables = OperationVariables>(
query: DocumentNode,
options?: LazyQueryHookOptions<TData, TVariables>
): LazyQueryResult<TData, TVariables>;
type LazyQueryResult<TData, TVariables> = [
LazyQueryExecuteFunction<TData, TVariables>,
QueryResult<TData, TVariables>
];
type LazyQueryExecuteFunction<TData, TVariables> = (
options?: QueryLazyOptions<TVariables>
) => Promise<QueryResult<TData, TVariables>>;
interface LazyQueryHookOptions<TData, TVariables>
extends Omit<QueryHookOptions<TData, TVariables>, 'skip'> {}
interface QueryLazyOptions<TVariables> {
/** Variables to pass to the query */
variables?: TVariables;
/** Context for the query */
context?: DefaultContext;
}Usage Examples:
import { useLazyQuery, gql } from "@apollo/react-hooks";
const SEARCH_USERS = gql`
query SearchUsers($query: String!) {
searchUsers(query: $query) {
id
name
email
}
}
`;
function UserSearch() {
const [searchUsers, { loading, error, data }] = useLazyQuery(SEARCH_USERS);
const handleSearch = (searchTerm: string) => {
searchUsers({ variables: { query: searchTerm } });
};
return (
<div>
<input
type="text"
onChange={(e) => handleSearch(e.target.value)}
placeholder="Search users..."
/>
{loading && <div>Searching...</div>}
{error && <div>Error: {error.message}</div>}
{data && (
<ul>
{data.searchUsers.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
);
}type FetchPolicy =
| 'cache-first'
| 'cache-only'
| 'cache-and-network'
| 'network-only'
| 'no-cache'
| 'standby';
type ErrorPolicy = 'none' | 'ignore' | 'all';
enum NetworkStatus {
loading = 1,
setVariables = 2,
fetchMore = 3,
refetch = 4,
poll = 6,
ready = 7,
error = 8,
}
interface FetchMoreQueryOptions<TVariables, K extends keyof TVariables> {
variables?: Pick<TVariables, K>;
}
interface FetchMoreOptions<TData, TVariables> {
updateQuery?: (
previousQueryResult: TData,
options: {
fetchMoreResult?: TData;
variables?: TVariables;
}
) => TData;
}