graphql-hooks
Features
-
🥇 First-class hooks API -
⚖️ Tiny bundle: only 3.7kB (1.4 gzipped) -
📄 Full SSR support: see graphql-hooks-ssr -
🔌 Plugin Caching: see graphql-hooks-memcache -
🔥 No more render props hell -
⏳ Handle loading and error states with ease
Install
npm install graphql-hooks
or
yarn add graphql-hooks
Quick Start
First you'll need to create a client and wrap your app with the provider:
import { GraphQLClient, ClientContext } from 'graphql-hooks';
const client = new GraphQLClient({
url: '/graphql'
});
function App() {
return (
<ClientContext.Provider value={client}>
{/* children */}
</ClientContext.Provider>
);
}
Now in your child components you can make use of useQuery
import { useQuery } from 'graphql-hooks';
const HOMEPAGE_QUERY = `query HomePage($limit: Int) {
users(limit: $limit) {
id
name
}
}`;
function MyComponent() {
const { loading, error, data } = useQuery(HOMEPAGE_QUERY, {
variables: {
limit: 10
}
});
if (loading) return 'Loading...';
if (error) return 'Something Bad Happened';
return (
<ul>
{data.users.map(({ id, name }) => (
<li key={id}>{name}</li>
))}
</ul>
);
}
Table of Contents
- API
- Guides
API
GraphQLClient
Usage:
import { GraphQLClient } from 'graphql-hooks';
const client = new GraphQLClient(config);
config
: Object containing configuration properties
url
(Required): The url to your GraphQL serverssrMode
: Boolean - set totrue
when using on the server for server-side rendering; defaults tofalse
cache
: Object with the following methods:cache.get(key)
cache.set(key, data)
cache.delete(key)
cache.clear()
cache.keys()
getInitialState()
- See graphql-hooks-memcache as a reference implementation
fetch(url, options)
: Fetch implementation - defaults to the globalfetch
APIfetchOptions
: See MDN for info on what options can be passedheaders
: Object, e.g.{ 'My-Header': 'hello' }
logErrors
: Boolean - defaults totrue
onError({ operation, result })
: Custom error handleroperation
: Object withquery
,variables
andoperationName
result
: Object containingerror
,data
,fetchError
,httpError
andgraphqlErrors
client
methods
client.setHeader(key, value)
: Updatesclient.headers
adding the new header to the existing headersclient.setHeaders(headers)
: Replacesclient.headers
client.logErrorResult({ operation, result })
: Default error logger; useful if you'd like to use it inside your customonError
handlerrequest(operation, options)
: Make a request to your GraphQL server; returning a Promiseoperation
: Object withquery
,variables
andoperationName
options.fetchOptionsOverrides
: Object containing additional fetch options to be added to the default ones passed tonew GraphQLClient(config)
ClientContext
ClientContext
is the result of React.createContext()
- meaning it can be used directly with React's new context API:
Example:
import { ClientContext } from 'graphql-hooks';
<ClientContext.Provider value={client}>
{/* children can now consume the client context */}
</ClientContext.Provider>;
To access the GraphQLClient
instance, call React.useContext(ClientContext)
:
import React, { useContext } from 'react';
import { ClientContext } from 'graphql-hooks';
function MyComponent() {
const client = useContext(ClientContext);
}
useQuery
Usage:
const state = useQuery(query, [options]);
Example:
import { useQuery } from 'graphql-hooks';
function MyComponent() {
const { loading, error, data } = useQuery(query);
if (loading) return 'Loading...';
if (error) return 'Something bad happened';
return <div>{data.thing}</div>;
}
This is a custom hook that takes care of fetching your query and storing the result in the cache. It won't refetch the query unless query
or options.variables
changes.
query
: Your GraphQL query as a plain stringoptions
: Object with the following optional propertiesvariables
: Object e.g.{ limit: 10 }
operationName
: If your query has multiple operations, pass the name of the operation you wish to execute.useCache
: Boolean - defaults totrue
; cache the query resultskipCache
: Boolean - defaults tofalse
; Iftrue
it will by-pass the cache and fetch, but the result will then be cached for subsequent calls. Note therefetch
function will do this automaticallyssr
: Boolean - defaults totrue
. Set tofalse
if you wish to skip this query during SSRfetchOptionsOverrides
: Object - Specific overrides for this query. See MDN for info on what options can be passed
useQuery
return value
const { loading, error, data, refetch, cacheHit, ...errors } = useQuery(QUERY);
loading
: Boolean -true
if the query is in flighterror
: Boolean -true
iffetchError
orhttpError
orgraphQLErrors
has been setdata
: Object - the result of your GraphQL queryrefetch
: Function - useful when refetching the same query after a mutation; NOTE this presetsskipCache=true
cacheHit
: Boolean -true
if the query result came from the cache, useful for debuggingfetchError
: Object - Set if an error occured during thefetch
callhttpError
: Object - Set if an error response was returned from the servergraphQLErrors
: Array - Populated if any errors occured whilst resolving the query
useManualQuery
Use this when you don't want a query to automactially be fetched, or wish to call a query programmatically.
Usage:
const [queryFn, state] = useManualQuery(query, [options]);
Example:
import { useManualQuery } from 'graphql-hooks'
function MyComponent(props) {
const [fetchUser, { loading, error, data }] = useManualQuery(GET_USER_QUERY, {
variables: { id: props.userId }
})
return (
<div>
<button onClick={fetchUser}>Get User!</button>
{error && <div>Failed to fetch user<div>}
{loading && <div>Loading...</div>}
{data && <div>Hello ${data.user.name}</div>}
</div>
)
}
If you don't know certain options when declaring the useManualQuery
you can also pass the same options to the query function itself when calling it:
import { useManualQuery } from 'graphql-hooks';
function MyComponent(props) {
const [fetchUser] = useManualQuery(GET_USER_QUERY);
const fetchUserThenSomething = async () => {
const user = await fetchUser({
variables: { id: props.userId }
});
return somethingElse();
};
return (
<div>
<button onClick={fetchUserThenSomething}>Get User!</button>
</div>
);
}
useMutation
Mutations unlike Queries are not cached.
Usage:
const [mutationFn, state] = useMutation(mutation, [options]);
Example:
import { useMutation } from 'graphql-hooks';
const UPDATE_USER_MUTATION = `mutation UpdateUser(id: String!, name: String!) {
updateUser(id: $id, name: $name) {
name
}
}`;
function MyComponent({ id, name }) {
const [updateUser] = useMutation(UPDATE_USER_MUTATION);
const [newName, setNewName] = useState(name);
return (
<div>
<input
type="text"
value={newName}
onChange={e => setNewName(e.target.value)}
/>
<button
onClick={() => updateUser({ variables: { id, name: newName } })}
/>
</div>
);
}
The options
object that can be passed either to useMutation(mutation, options)
or mutationFn(options)
can be set with the following properties:
variables
: Object e.g.{ limit: 10 }
operationName
: If your query has multiple operations, pass the name of the operation you wish to execute.fetchOptionsOverrides
: Object - Specific overrides for this query. See MDN for info on what options can be passed
Guides
SSR
See graphql-hooks-ssr for an in depth guide.
Authentication
Coming soon!
Fragments
Coming soon!
Migrating from Apollo
Coming soon!