---
title: React/Preact Bindings
order: 0
---
# React/Preact
This guide covers how to install and setup `urql` and the `Client`, as well as query and mutate data,
with React and Preact. Since the `urql` and `@urql/preact` packages share most of their API and are
used in the same way, when reading the documentation on React, all examples are essentially the same,
except that we'd want to use the `@urql/preact` package instead of the `urql` package.
## Getting started
### Installation
Installing `urql` is as quick as you'd expect, and you won't need any other packages to get started
with at first. We'll install the package with our package manager of choice.
```sh
yarn add urql
# or
npm install --save urql
```
To use `urql` with Preact, we have to install `@urql/preact` instead of `urql` and import from
that package instead. Otherwise all examples for Preact will be the same.
Most libraries related to GraphQL also need the `graphql` package to be installed as a peer
dependency, so that they can adapt to your specific versioning requirements. That's why we'll need
to install `graphql` alongside `urql`.
Both the `urql` and `graphql` packages follow [semantic versioning](https://semver.org) and all
`urql` packages will define a range of compatible versions of `graphql`. Watch out for breaking
changes in the future however, in which case your package manager may warn you about `graphql` being
out of the defined peer dependency range.
### Setting up the `Client`
The `urql` and `@urql/preact` packages export a `Client` class, which we can use to
create the GraphQL client. This central `Client` manages all of our GraphQL requests and results.
```js
import { Client, cacheExchange, fetchExchange } from 'urql';
const client = new Client({
url: 'http://localhost:3000/graphql',
exchanges: [cacheExchange, fetchExchange],
});
```
At the bare minimum we'll need to pass an API's `url` and `exchanges` when we create a `Client`
to get started.
Another common option is `fetchOptions`. This option allows us to customize the options that will be
passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object, or
a function returning an options object.
In the following example we'll add a token to each `fetch` request that our `Client` sends to our
GraphQL API.
```js
const client = new Client({
url: 'http://localhost:3000/graphql',
exchanges: [cacheExchange, fetchExchange],
fetchOptions: () => {
const token = getToken();
return {
headers: { authorization: token ? `Bearer ${token}` : '' },
};
},
});
```
### Providing the `Client`
To make use of the `Client` in React & Preact we will have to provide it via the
[Context API](https://reactjs.org/docs/context.html). This may be done with the help of
the `Provider` export.
```jsx
import { Client, Provider, cacheExchange, fetchExchange } from 'urql';
const client = new Client({
url: 'http://localhost:3000/graphql',
exchanges: [cacheExchange, fetchExchange],
});
const App = () => (
);
```
Now every component and element inside and under the `Provider` can use GraphQL queries that
will be sent to our API.
## Queries
Both libraries offer a `useQuery` hook and a `Query` component. The latter accepts the same
parameters, but we won't cover it in this guide. [Look it up in the API docs if you prefer
render-props components.](../api/urql.md#query-component)
### Run a first query
For the following examples, we'll imagine that we're querying data from a GraphQL API that contains
todo items. Let's dive right into it!
```jsx
import { gql, useQuery } from 'urql';
const TodosQuery = gql`
query {
todos {
id
title
}
}
`;
const Todos = () => {
const [result, reexecuteQuery] = useQuery({
query: TodosQuery,
});
const { data, fetching, error } = result;
if (fetching) return
Loading...
;
if (error) return Oh no... {error.message}
;
return (
{data.todos.map(todo => (
- {todo.title}
))}
);
};
```
Here we have implemented our first GraphQL query to fetch todos. We see that `useQuery` accepts
options and returns a tuple. In this case we've set the `query` option to our GraphQL query. The
tuple we then get in return is an array that contains a result object, and a re-execute function.
The result object contains several properties. The `fetching` field indicates whether the hook is
loading data, `data` contains the actual `data` from the API's result, and `error` is set when either
the request to the API has failed or when our API result contained some `GraphQLError`s, which
we'll get into later on the ["Errors" page](./errors.md).
### Variables
Typically we'll also need to pass variables to our queries, for instance, if we are dealing with
pagination. For this purpose the `useQuery` hook also accepts a `variables` option, which we can use
to supply variables to our query.
```jsx
const TodosListQuery = gql`
query ($from: Int!, $limit: Int!) {
todos(from: $from, limit: $limit) {
id
title
}
}
`;
const Todos = ({ from, limit }) => {
const [result, reexecuteQuery] = useQuery({
query: TodosListQuery,
variables: { from, limit },
});
// ...
};
```
As when we're sending GraphQL queries manually using `fetch`, the variables will be attached to the
`POST` request body that is sent to our GraphQL API.
Whenever the `variables` (or the `query`) option on the `useQuery` hook changes `fetching` will
switch to `true`, and a new request will be sent to our API, unless a result has already been cached
previously.
### Pausing `useQuery`
In some cases we may want `useQuery` to execute a query when a pre-condition has been met, and not
execute the query otherwise. For instance, we may be building a form and want a validation query to
only take place when a field has been filled out.
Since hooks in React can't just be commented out, the `useQuery` hook accepts a `pause` option that
temporarily _freezes_ all changes and stops requests.
In the previous example we've defined a query with mandatory arguments. The `$from` and `$limit`
variables have been defined to be non-nullable `Int!` values.
Let's pause the query we've just
written to not execute when these variables are empty, to prevent `null` variables from being
executed. We can do this by setting the `pause` option to `true`:
```jsx
const Todos = ({ from, limit }) => {
const shouldPause = from === undefined || from === null || limit === undefined || limit === null;
const [result, reexecuteQuery] = useQuery({
query: TodosListQuery,
variables: { from, limit },
pause: shouldPause,
});
// ...
};
```
Now whenever the mandatory `$from` or `$limit` variables aren't supplied the query won't be executed.
This also means that `result.data` won't change, which means we'll still have access to our old data
even though the variables may have changed.
### Request Policies
As has become clear in the previous sections of this page, the `useQuery` hook accepts more options
than just `query` and `variables`. Another option we should touch on is `requestPolicy`.
The `requestPolicy` option determines how results are retrieved from our `Client`'s cache. By
default, this is set to `cache-first`, which means that we prefer to get results from our cache, but
are falling back to sending an API request.
Request policies aren't specific to `urql`'s React API, but are a common feature in its core. [You
can learn more about how the cache behaves given the four different policies on the "Document
Caching" page.](../basics/document-caching.md)
```jsx
const [result, reexecuteQuery] = useQuery({
query: TodosListQuery,
variables: { from, limit },
requestPolicy: 'cache-and-network',
});
```
Specifically, a new request policy may be passed directly to the `useQuery` hook as an option.
This policy is then used for this specific query. In this case, `cache-and-network` is used and
the query will be refreshed from our API even after our cache has given us a cached result.
Internally, the `requestPolicy` is just one of several "**context** options". The `context`
provides metadata apart from the usual `query` and `variables` we may pass. This means that
we may also change the `Client`'s default `requestPolicy` by passing it there.
```js
import { Client, cacheExchange, fetchExchange } from 'urql';
const client = new Client({
url: 'http://localhost:3000/graphql',
exchanges: [cacheExchange, fetchExchange],
// every operation will by default use cache-and-network rather
// than cache-first now:
requestPolicy: 'cache-and-network',
});
```
### Context Options
As mentioned, the `requestPolicy` option on `useQuery` is a part of `urql`'s context options.
In fact, there are several more built-in context options, and the `requestPolicy` option is
one of them. Another option we've already seen is the `url` option, which determines our
API's URL. These options aren't limited to the `Client` and may also be passed per query.
```jsx
import { useMemo } from 'react';
import { useQuery } from 'urql';
const Todos = ({ from, limit }) => {
const [result, reexecuteQuery] = useQuery({
query: TodosListQuery,
variables: { from, limit },
context: useMemo(
() => ({
requestPolicy: 'cache-and-network',
url: 'http://localhost:3000/graphql?debug=true',
}),
[]
),
});
// ...
};
```
As we can see, the `context` property for `useQuery` accepts any known `context` option and can be
used to alter them per query rather than globally. The `Client` accepts a subset of `context`
options, while the `useQuery` option does the same for a single query.
[You can find a list of all `Context` options in the API docs.](../api/core.md#operationcontext)
### Reexecuting Queries
The `useQuery` hook updates and executes queries whenever its inputs, like the `query` or
`variables` change, but in some cases we may find that we need to programmatically trigger a new
query. This is the purpose of the `reexecuteQuery` function, which is the second item in the tuple
that `useQuery` returns.
Triggering a query programmatically may be useful in a couple of cases. It can for instance be used
to refresh the hook's data. In these cases we may also override the `requestPolicy` of our query just
once and set it to `network-only` to skip the cache.
```jsx
const Todos = ({ from, limit }) => {
const [result, reexecuteQuery] = useQuery({
query: TodosListQuery,
variables: { from, limit },
});
const refresh = () => {
// Refetch the query and skip the cache
reexecuteQuery({ requestPolicy: 'network-only' });
};
};
```
Calling `refresh` in the above example will execute the query again forcefully, and will skip the
cache, since we're passing `requestPolicy: 'network-only'`.
Furthermore the `reexecuteQuery` function can also be used to programmatically start a query even
when `pause` is set to `true`, which would usually stop all automatic queries. This can be used to
perform one-off actions, or to set up polling.
```jsx
import { useEffect } from 'react';
import { useQuery } from 'urql';
const Todos = ({ from, limit }) => {
const [result, reexecuteQuery] = useQuery({
query: TodosListQuery,
variables: { from, limit },
pause: true,
});
useEffect(() => {
if (result.fetching) return;
// Set up to refetch in one second, if the query is idle
const timerId = setTimeout(() => {
reexecuteQuery({ requestPolicy: 'network-only' });
}, 1000);
return () => clearTimeout(timerId);
}, [result.fetching, reexecuteQuery]);
// ...
};
```
There are some more tricks we can use with `useQuery`. [Read more about its API in the API docs for
it.](../api/urql.md#usequery)
## Mutations
Both libraries offer a `useMutation` hook and a `Mutation` component. The latter accepts the same
parameters, but we won't cover it in this guide. [Look it up in the API docs if you prefer
render-props components.](../api/urql.md#mutation-component)
### Sending a mutation
Let's again pick up an example with an imaginary GraphQL API for todo items, and dive into an
example! We'll set up a mutation that _updates_ a todo item's title.
```jsx
const UpdateTodo = `
mutation ($id: ID!, $title: String!) {
updateTodo (id: $id, title: $title) {
id
title
}
}
`;
const Todo = ({ id, title }) => {
const [updateTodoResult, updateTodo] = useMutation(UpdateTodo);
};
```
Similar to the `useQuery` output, `useMutation` returns a tuple. The first item in the tuple again
contains `fetching`, `error`, and `data` — it's identical since this is a common pattern of how
`urql` presents [operation results](../api/core.md#operationresult).
Unlike the `useQuery` hook, the `useMutation` hook doesn't execute automatically. At this point in
our example, no mutation will be performed. To execute our mutation we instead have to call the
execute function — `updateTodo` in our example — which is the second item in the tuple.
### Using the mutation result
When calling our `updateTodo` function we have two ways of getting to the result as it comes back
from our API. We can either use the first value of the returned tuple, our `updateTodoResult`, or
we can use the promise that `updateTodo` returns.
```jsx
const Todo = ({ id, title }) => {
const [updateTodoResult, updateTodo] = useMutation(UpdateTodo);
const submit = newTitle => {
const variables = { id, title: newTitle || '' };
updateTodo(variables).then(result => {
// The result is almost identical to `updateTodoResult` with the exception
// of `result.fetching` not being set.
// It is an OperationResult.
});
};
};
```
The result is useful when your UI has to display progress on the mutation, and the returned
promise is particularly useful when you're adding side effects that run after the mutation has
completed.
### Handling mutation errors
It's worth noting that the promise we receive when calling the execute function will never
reject. Instead it will always return a promise that resolves to a result.
If you're checking for errors, you should use `result.error` instead, which will be set
to a `CombinedError` when any kind of errors occurred while executing your mutation.
[Read more about errors on our "Errors" page.](./errors.md)
```jsx
const Todo = ({ id, title }) => {
const [updateTodoResult, updateTodo] = useMutation(UpdateTodo);
const submit = newTitle => {
const variables = { id, title: newTitle || '' };
updateTodo(variables).then(result => {
if (result.error) {
console.error('Oh no!', result.error);
}
});
};
};
```
There are some more tricks we can use with `useMutation`.
[Read more about its API in the API docs for it.](../api/urql.md#usemutation)
## Reading on
This concludes the introduction for using `urql` with React or Preact. The rest of the documentation
is mostly framework-agnostic and will apply to either `urql` in general, or the `@urql/core` package,
which is the same between all framework bindings. Hence, next we may want to learn more about one of
the following to learn more about the internals:
- [How does the default "document cache" work?](./document-caching.md)
- [How are errors handled and represented?](./errors.md)
- [A quick overview of `urql`'s architecture and structure.](../architecture.md)
- [Setting up other features, like authentication, uploads, or persisted queries.](../advanced/README.md)