urql Documentation

The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

8,946 stars TypeScript TypeScript 1 file Β· ~20,106 tokens #complex-apps#exchange#graphql#graphql-client#graphql-clients
RAW Doc

File: README.md

✨ Features

urql is a GraphQL client that exposes a set of helpers for several frameworks. It's built to be highly customisable and versatile so
you can take it from getting started with your first GraphQL project all the way to building complex apps and experimenting with GraphQL clients.

πŸ“ƒ For more information, check out the docs.

πŸ’™ [Sponsors](https://github.com/sponsors/urql-graphql)

BigCommerce WunderGraph The Guild
BeatGig

πŸ™Œ Contributing

The urql project was founded by Formidable and is actively developed
by the urql GraphQL team.

If you'd like to get involved, check out our Contributor's guide.

πŸ“¦ [Releases](https://github.com/urql-graphql/urql/releases)

All new releases and updates are listed on GitHub with full changelogs. Each package in this
repository further contains an independent CHANGELOG.md file with the historical changelog, for
instance, here’s @urql/core’s
changelog
.

If you’re upgrading to v4, check out our migration guide, posted as an
issue.

New releases are prepared using
changesets,
which are changelog entries added to each PR, and we have β€œVersion Packages” PRs that once merged
will release new versions of urql packages. You can use @canary releases from npm if you’d
like to get a preview of the merged changes.

πŸ“ƒ [Documentation](https://urql.dev/goto/docs)

The documentation contains everything you need to know about urql, and contains several sections in order of importance
when you first get started:

Furthermore, all APIs and packages are self-documented using TSDocs. If you’re using a language
server for TypeScript, the documentation for each API should pop up in your editor when hovering
urql’s code and APIs.

You can find the raw markdown files inside this repository's docs folder.


File: docs/api/auth-exchange.md


title: '@urql/exchange-auth' order: 10

Authentication Exchange

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/exchange-auth package contains an addon authExchange for urql that aims to make it
easy to implement complex authentication and reauthentication flows as are typically found with JWT
token based API authentication.

Installation and Setup

First install @urql/exchange-auth alongside urql:

sh
yarn add @urql/exchange-auth
# or
npm install --save @urql/exchange-auth

You'll then need to add the authExchange, that this package exposes to your Client. The
authExchange is an asynchronous exchange, so it must be placed in front of all fetchExchanges
but after all other synchronous exchanges, like the cacheExchange.

js
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { authExchange } from '@urql/exchange-auth';

const client = createClient({
  url: 'http://localhost:3000/graphql',
  exchanges: [
    cacheExchange,
    authExchange(async utils => {
      return {
        /* config... */
      };
    }),
    fetchExchange,
  ],
});

The authExchange accepts an initialization function. This function is called when your exchange
and Client first start up, and must return an object of options wrapped in a Promise, which is
used to configure how your authentication method works.

You can use this function to first retrieve your authentication state from a kind
of local storage, or to call your API to validate your authentication state first.

The relevant configuration options, returned to the authExchange, then determine
how the authExchange behaves:

  • addAuthToOperation must be provided to tell authExchange how to add authentication information
    to an operation, e.g. how to add the authentication state to an operation's fetch headers.
  • willAuthError may be provided to detect expired tokens or tell whether an operation will likely
    fail due to an authentication error.
  • didAuthError may be provided to let the authExchange detect authentication errors from the
    API on results.
  • refreshAuth is called when an authentication error occurs and gives you an opportunity to update
    your authentication state. Afterwards, the authExchange will retry your operation.

Read more examples in the documentation given here.


File: docs/api/core.md


title: '@urql/core' order: 0

@urql/core

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/core package is the basis of all framework bindings. Each bindings-package,
like urql for React or @urql/preact, will reuse the core logic and
reexport all exports from @urql/core.
Therefore if you're not accessing utilities directly, aren't in a Node.js environment, and are using
framework bindings, you'll likely want to import from your framework bindings package directly.

Read more about urql's core on the "Core Package" page.

Client

The Client manages all operations and ongoing requests to the exchange pipeline.
It accepts several options on creation.

@urql/core also exposes createClient() that is just a convenient alternative to calling new Client().

Input Type Description
exchanges Exchange[] An array of Exchanges that the client should use
url string The GraphQL API URL as used by fetchExchange
fetchOptions RequestInit | () => RequestInit Additional fetchOptions that fetch in fetchExchange should use to make a request
fetch typeof fetch An alternative implementation of fetch that will be used by the fetchExchange instead of window.fetch
suspense ?boolean Activates the experimental React suspense mode, which can be used during server-side rendering to prefetch data
requestPolicy ?RequestPolicy Changes the default request policy that will be used. By default, this will be cache-first.
preferGetMethod ?boolean | 'force' | 'within-url-limit' This is picked up by the fetchExchange and will force all queries (not mutations) to be sent using the HTTP GET method instead of POST if the length of the resulting URL doesn't exceed 2048 characters. When 'force' is passed a GET request is always sent regardless of how long the resulting URL is.

client.executeQuery

Accepts a GraphQLRequest and optionally Partial<OperationContext>, and returns a
Source<OperationResult> β€” a stream of query results that can be subscribed to.

Internally, subscribing to the returned source will create an Operation, with
kind set to 'query', and dispatch it on the
exchanges pipeline. If no subscribers are listening to this operation anymore and unsubscribe from
the query sources, the Client will dispatch a "teardown" operation.

client.executeSubscription

This is functionally the same as client.executeQuery, but creates operations for subscriptions
instead, with kind set to 'subscription'.

client.executeMutation

This is functionally the same as client.executeQuery, but creates operations for mutations
instead, with kind set to 'mutation'.

A mutation source is always guaranteed to only respond with a single OperationResult and then complete.

client.query

This is a shorthand method for client.executeQuery, which accepts a query
(DocumentNode | string) and variables separately and creates a GraphQLRequest createRequest automatically.

The returned Source<OperationResult> will also have an added toPromise method, so the stream can
be conveniently converted to a promise.

js
import { pipe, subscribe } from 'wonka';

const { unsubscribe } = pipe(
  client.query('{ test }', {
    /* vars */
  }),
  subscribe(result => {
    console.log(result); // OperationResult
  })
);

// or with toPromise, which also limits this to one result
client
  .query('{ test }', {
    /* vars */
  })
  .toPromise()
  .then(result => {
    console.log(result); // OperationResult
  });

Read more about how to use this API on the "Core Package"
page.

client.mutation

This is similar to client.query, but dispatches mutations instead.

Read more about how to use this API on the "Core Package"
page.

client.subscription

This is similar to client.query, but does not provide a toPromise() helper method on the streams it returns.

Read more about how to use this API on the "Subscriptions" page.

client.reexecuteOperation

This method is commonly used in Exchanges to reexecute an Operation on the
Client. It will only reexecute when there are still subscribers for the given
Operation.

For an example, this method is used by the cacheExchange when an
OperationResult is invalidated in the cache and needs to be refetched.

client.readQuery

This method is typically used to read data synchronously from a cache. It returns an OperationResult if a value is returned immediately or null if no value is returned while cancelling all side effects.

CombinedError

The CombinedError is used in urql to normalize network errors and GraphQLErrors if anything
goes wrong during a GraphQL request.

Input Type Description
networkError ?Error An unexpected error that might've occurred when trying to send the GraphQL request
graphQLErrors ?Array<string | GraphQLError> GraphQL Errors (if any) that were returned by the GraphQL API
response ?any The raw response object (if any) from the fetch call

Read more about errors in urql on the "Error" page.

Types

GraphQLRequest

This often comes up as the input for every GraphQL request.
It consists of query and optionally variables.

Prop Type Description
key number A unique key that identifies this exact combination of query and variables, which is derived using a stable hash.
query DocumentNode The query to be executed. Accepts as a plain string query or GraphQL DocumentNode.
variables ?object The variables to be used with the GraphQL request.

The key property is a hash of both the query and the variables, to uniquely
identify the request. When variables are passed it is ensured that they're stably stringified so
that the same variables in a different order will result in the same key, since variables are
order-independent in GraphQL.

A GraphQLRequest may be manually created using the createRequest helper.

OperationType

This determines what kind of operation the exchanges need to perform.
This is one of:

  • 'subscription'
  • 'query'
  • 'mutation'
  • 'teardown'

The 'teardown' operation is special in that it instructs exchanges to cancel
any ongoing operations with the same key as the 'teardown' operation that is
received.

Operation

The input for every exchange that informs GraphQL requests.
It extends the GraphQLRequest type and contains these additional properties:

Prop Type Description
kind OperationType The type of GraphQL operation being executed.
context OperationContext Additional metadata passed to exchange.

An Operation also contains the operationName property, which is a deprecated alias of the kind
property and outputs a deprecation warning if it's used.

RequestPolicy

This determines the strategy that a cache exchange should use to fulfill an operation.
When you implement a custom cache exchange it's recommended that these policies are
handled.

  • 'cache-first' (default)
  • 'cache-only'
  • 'network-only'
  • 'cache-and-network'

Read more about request policies on the "Document Caching" page.

OperationContext

The context often carries options or metadata for individual exchanges, but may also contain custom
data that can be passed from almost all API methods in urql that deal with
Operations.

Some of these options are set when the Client is initialised, so in the following list of
properties you'll likely see some options that exist on the Client as well.

Prop Type Description
fetchOptions ?RequestInit | (() => RequestInit) Additional fetchOptions that fetch in fetchExchange should use to make a request.
fetch typeof fetch An alternative implementation of fetch that will be used by the fetchExchange instead of window.fetch
requestPolicy RequestPolicy An optional request policy that should be used specifying the cache strategy.
url string The GraphQL endpoint, when using GET you should use absolute url's
meta ?OperationDebugMeta Metadata that is only available in development for devtools.
suspense ?boolean Whether suspense is enabled.
preferGetMethod ?boolean | 'force' | 'within-url-limit' Instructs the fetchExchange to use HTTP GET for queries.
additionalTypenames ?string[] Allows you to tell the operation that it depends on certain typenames (used in document-cache.)

It also accepts additional, untyped parameters that can be used to send more
information to custom exchanges.

OperationResult

The result of every GraphQL request, i.e. an Operation. It's very similar to what comes back from
a typical GraphQL API, but slightly enriched and normalized.

Prop Type Description
operation Operation The operation that this is a result for
data ?any Data returned by the specified query
error ?CombinedError A CombinedError instances that wraps network or GraphQLErrors (if any)
extensions ?Record<string, any> Extensions that the GraphQL server may have returned.
stale ?boolean A flag that may be set to true by exchanges to indicate that the data is incomplete or out-of-date, and that the result will be updated soon.

ExchangeInput

This is the input that an Exchange receives when it's initialized by the
Client

Input Type Description
forward ExchangeIO The unction responsible for receiving an observable operation and returning a result
client Client The urql application-wide client library. Each execute method starts a GraphQL request and returns a stream of results.

Exchange

An exchange represents abstractions of small chunks of logic in urql.
They're small building blocks and similar to "middleware".

Read more about Exchanges on the "Authoring Exchanges" page.

An exchange is defined to be a function that receives ExchangeInput and returns
an ExchangeIO function. The ExchangeIO function in turn will receive a stream of operations, and
must return a stream of results. If the exchange is purely transforming data, like the
mapExchange for instance, it'll call forward, which is the next Exchange's ExchangeIO
function to get a stream of results.

js
type ExchangeIO = (Source<Operation>) => Source<OperationResult>;
type Exchange = ExchangeInput => ExchangeIO;

If you haven't yet seen streams you can read more about "Stream Patterns" on the "Architecture"
page.

Exchanges

cacheExchange

The cacheExchange as described on the "Document Caching" page.. It's of type Exchange.

subscriptionExchange

The subscriptionExchange as described on the "Subscriptions" page.. It's of type Options => Exchange.

It accepts a single input: { forwardSubscription }. This is a function that
receives an enriched operation and must return an Observable-like object that
streams GraphQLResults with data and errors.

The forwardSubscription function is commonly connected to the subscriptions-transport-ws
package
.

ssrExchange

The ssrExchange as described on the "Server-side Rendering"
page.
.
It's of type Options => Exchange.

It accepts three inputs, initialState which is completely
optional and populates the server-side rendered data with
a rehydrated cache, isClient which can be set to
true or false to tell the ssrExchange whether to
write to (server-side) or read from (client-side) the cache, and
staleWhileRevalidate which will treat rehydrated data as stale
and refetch up-to-date data by reexecuring the operation using a network-only requests policy.

By default, isClient defaults to true when the Client.suspense
mode is disabled and to false when the Client.suspense mode
is enabled.

This can be used to extract data that has been queried on
the server-side, which is also described in the Basics section,
and is also used on the client-side to restore server-side
rendered data.

When called, this function creates an Exchange, which also has
two methods on it:

  • .restoreData(data) which can be used to inject data, typically
    on the client-side.
  • .extractData() which is typically used on the server-side to
    extract the server-side rendered data.

Basically, the ssrExchange is a small cache that collects data
during the server-side rendering pass, and allows you to populate
the cache on the client-side with the same data.

During React rehydration this cache will be emptied, and it will
become inactive and won't change the results of queries after
rehydration.

It needs to be used after other caching Exchanges like the
cacheExchange, but before any asynchronous Exchange like
the fetchExchange.

debugExchange

An exchange that writes incoming Operations to console.log and
writes completed OperationResults to console.log.

This exchange is disabled in production and is based on the mapExchange.
If you'd like to customise it, you can replace it with a custom mapExchange.

fetchExchange

The fetchExchange of type Exchange is responsible for sending operations of type 'query' and
'mutation' to a GraphQL API using fetch.

mapExchange

The mapExchange allows you to:

  • react to or replace operations with onOperation,
  • react to or replace results with onResult,
  • and; react to errors in results with onError.

It can therefore be used to quickly react to the core events in the Client without writing a custom
exchange, effectively allowing you to ship your own debugExchange.

ts
mapExchange({
  onOperation(operation) {
    console.log('operation', operation);
  },
  onResult(result) {
    console.log('result', result);
  },
});

It can also be used to react only to errors, which is the same as checking for result.error:

ts
mapExchange({
  onError(error, operation) {
    console.log(`The operation ${operation.key} has errored with:`, error);
  },
});

Lastly, it can be used to map operations and results, which may be useful to update the
OperationContext or perform other standard tasks that require you to wait for a result:

ts
import { mapExchange, makeOperation } from '@urql/core';

mapExchange({
  async onOperation(operation) {
    // NOTE: This is only for illustration purposes
    return makeOperation(operation.kind, operation, {
      ...operation.context,
      test: true,
    });
  },
  async onResult(result) {
    // NOTE: This is only for illustration purposes
    if (result.data === undefined) result.data = null;
    return result;
  },
});

errorExchange (deprecated)

An exchange that lets you inspect errors. This can be useful for logging, or reacting to
different types of errors (e.g. logging the user out in case of a permission error).

In newer versions of @urql/core, it's identical to the mapExchange and its export has been
replaced as the mapExchange also allows you to pass an onError function.

Utilities

gql

This is a gql tagged template literal function, similar to the one that's also commonly known from
graphql-tag. It can be used to write GraphQL documents in a tagged template literal and returns a
parsed DocumentNode that's primed against the createRequest's cache for keys.

js
import { gql } from '@urql/core';

const SharedFragment = gql`
  fragment UserFrag on User {
    id
    name
  }
`;

gql`
  query {
    user
    ...UserFrag
  }

  ${SharedFragment}
`;

Unlike graphql-tag, this function outputs a warning in development when names of fragments in the
document are duplicated. It does not output warnings when fragment names were duplicated globally
however.

stringifyVariables

This function is a variation of JSON.stringify that sorts any object's keys that is being
stringified to ensure that two objects with a different order of keys will be stably stringified to
the same string.

js
stringifyVariables({ a: 1, b: 2 }); // {"a":1,"b":2}
stringifyVariables({ b: 2, a: 1 }); // {"a":1,"b":2}

createRequest

This utility accepts a GraphQL query of type string | DocumentNode and optionally an object of
variables, and returns a GraphQLRequest object.

Since the client.executeQuery and other execute methods only accept
GraphQLRequests, this helper is commonly used to create that request first. The
client.query and client.mutation methods use this helper as
well to create requests.

The helper takes care of creating a unique key for the GraphQLRequest. This is a hash of the
query and variables if they're passed. The variables will be stringified using
stringifyVariables, which outputs a stable JSON string.

Additionally, this utility will ensure that the query reference will remain stable. This means
that if the same query will be passed in as a string or as a fresh DocumentNode, then the output
will always have the same DocumentNode reference.

makeOperation

This utility is used to either turn a GraphQLRequest object into a new
Operation object or to copy an Operation. It adds the kind property, and the
operationName alias that outputs a deprecation warning.

It accepts three arguments:

Hence some valid uses of the utility are:

js
// Create a new operation from scratch
makeOperation('query', createRequest(query, variables), client.createOperationContext(opts));

// Turn an operation into a 'teardown' operation
makeOperation('teardown', operation);

// Copy an existing operation while modifying its context
makeOperation(operation.kind, operation, {
  ...operation.context,
  preferGetMethod: true,
});

makeResult

This is a helper function that converts a GraphQL API result to an
OperationResult.

It accepts an Operation, the API result, and optionally the original FetchResponse
for debugging as arguments, in that order.

makeErrorResult

This is a helper function that creates an OperationResult for GraphQL API
requests that failed with a generic or network error.

It accepts an Operation, the error, and optionally the original FetchResponse
for debugging as arguments, in that order.

formatDocument

This utility is used by the cacheExchange and by
Graphcache to add __typename fields to GraphQL DocumentNodes.

composeExchanges

This utility accepts an array of Exchanges and composes them into a single one.
It chains them in the order that they're given, left to right.

js
function composeExchanges(Exchange[]): Exchange;

This can be used to combine some exchanges and is also used by Client
to handle the exchanges input.


File: docs/api/execute-exchange.md


title: '@urql/exchange-execute' order: 6

Execute Exchange

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/exchange-execute package contains an addon executeExchange for urql that may be used to
execute queries against a local schema. It is therefore a drop-in replacement for the default
fetchExchange and useful for the server-side, debugging, or testing.

Installation and Setup

First install @urql/exchange-execute alongside urql:

sh
yarn add @urql/exchange-execute
# or
npm install --save @urql/exchange-execute

You'll then need to add the executeExchange, exposed by this package, to your Client.
It'll typically replace the fetchExchange or similar exchanges and must be used last if possible,
since it'll handle operations and return results.

js
import { createClient, cacheExchange } from 'urql';
import { executeExchange } from '@urql/exchange-execute';

const client = createClient({
  url: 'http://localhost:3000/graphql',
  exchanges: [
    cacheExchange,
    executeExchange({
      /* config */
    }),
  ],
});

The executeExchange accepts an object of options, which are all similar to the arguments that
graphql/execution/execute accepts. Typically you'd pass it the schema option, some resolvers
if your schema isn't already executable as fieldResolver / typeResolver / rootValue,
and a context value or function.

Options

Option Description
schema This is of type GraphQLSchema and accepts either a schema that is or isn't executable. This field is required while all other fields are optional.
rootValue The root value that graphql's execute will use when starting to execute the schema.
fieldResolver A given field resolver function. Creating an executable schema may be easier than providing this, but this resolver will be passed on to execute as expected.
typeResolver A given type resolver function. Creating an executable schema may be easier than providing this, but this resolver will be passed on to execute as expected.
context This may either be a function that receives an Operation and returns the context value, or just a plain context value. Similarly to a GraphQL server this is useful as all resolvers will have access to your context

File: docs/api/graphcache.md


title: '@urql/exchange-graphcache' order: 4

@urql/exchange-graphcache

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/exchange-graphcache package contains an addon cacheExchange for urql that may be
used to replace the default cacheExchange, which switches urql from
using "Document Caching" to "Normalized
Caching"
.

Read more about how to use and configure Graphcache in the "Graphcache"
section

cacheExchange

The cacheExchange function, as exported by @urql/exchange-graphcache, accepts a single object of
options and returns an Exchange.

Input Description
keys A mapping of key generator functions for types that are used to override the default key generation that Graphcache uses to normalize data for given types.
resolvers A nested mapping of resolvers, which are used to override the record or entity that Graphcache resolves for a given field for a type.
directives A mapping of directives, which are functions accepting directive arguments and returning a resolver, which can be referenced by @localDirective or @_localDirective in queries.
updates A nested mapping of updater functions for mutation and subscription fields, which may be used to add side-effects that update other parts of the cache when the given subscription or mutation field is written to the cache.
optimistic A mapping of mutation fields to resolvers that may be used to provide Graphcache with an optimistic result for a given mutation field that should be applied to the cached data temporarily.
schema A serialized GraphQL schema that is used by Graphcache to resolve partial data, interfaces, and enums. The schema also used to provide helpful warnings for schema awareness.
storage A persisted storage interface that may be provided to preserve cache data for offline support.
globalIDs A boolean or list of typenames that have globally unique ids, this changes how graphcache internally keys the entities. This can be useful for complex interface relationships.
logger A function that will be invoked for warning/debug/... logs

The @urql/exchange-graphcache package also exports the offlineExchange; which is identical to
the cacheExchange but activates offline support when the storage option is passed.

`keys` option

This is a mapping of typenames to KeyGenerator functions.

ts
interface KeyingConfig {
  [typename: string]: (data: Data) => null | string;
}

It may be used to alter how Graphcache generates the key it uses for normalization for individual
types. The key generator function may also always return null when a type should always be
embedded.

Read more about how to set up keys in the "Key Generation" section of the "Normalized Caching"
page.

`resolvers` option

This configuration is a mapping of typenames to field names to Resolver functions.
A resolver may be defined to override the entity or record that a given field on a type should
resolve on the cache.

ts
interface ResolverConfig {
  [typeName: string]: {
    [fieldName: string]: Resolver;
  };
}

A Resolver receives four arguments when it's called: parent, args, cache, and
info.

Argument Type Description
parent Data The parent entity that the given field is on.
args object The arguments for the given field the updater is executed on.
cache Cache The cache using which data can be read or written. See Cache.
info Info Additional metadata and information about the current operation and the current field. See Info.

We can use the arguments it receives to either return new data based on just the arguments and other
cache information, but we may also read information about the parent and return new data for the
current field.

js
{
  Todo: {
    createdAt(parent, args, cache) {
      // Read `createdAt` on the parent but return a Date instance
      const date = cache.resolve(parent, 'createdAt');
      return new Date(date);
    }
  }
}

Read more about how to set up resolvers on the "Computed Queries"
page.

`updates` option

The updates configuration is a mapping of 'Mutation' | 'Subscription' to field names to
UpdateResolver functions. An update resolver may be defined to add side-effects that run when a
given mutation field or subscription field is written to the cache. These side-effects are helpful
to update data in the cache that is implicitly changed on the GraphQL API, that Graphcache can't
know about automatically.

For mutation fields that don't have an updater, Graphcache has a fallback: if a returned entity
isn't currently found in the cache, it assumes a create-mutation and invalidates cached
entities of that type. This behavior was introduced in Graphcache v7 and is skipped once an updater
for the mutation field is added.

ts
interface UpdatesConfig {
  Mutation: {
    [fieldName: string]: UpdateResolver;
  };
  Subscription: {
    [fieldName: string]: UpdateResolver;
  };
}

An UpdateResolver receives four arguments when it's called: result, args, cache, and
info.

Argument Type Description
result any Always the entire data object from the mutation or subscription.
args object The arguments for the given field the updater is executed on.
cache Cache The cache using which data can be read or written. See Cache.
info Info Additional metadata and information about the current operation and the current field. See Info.

It's possible to derive more information about the current update using the info argument. For
instance this metadata contains the current fieldName of the updater which may be used to make an
updater function more reusable, along with parentKey and other key fields. It also contains
variables and fragments which remain the same for the entire write operation, and additionally
it may have the error field set to describe whether the current field is null because the API
encountered a GraphQLError.

Read more about how to set up updates on the "Custom Updates"
page.

`optimistic` option

The optimistic configuration is a mapping of Mutation field names to OptimisticMutationResolver
functions, which return optimistic mutation results for given fields. These results are used by
Graphcache to optimistically update the cache data, which provides an immediate and temporary
change to its data before a mutation completes.

ts
interface OptimisticMutationConfig {
  [mutationFieldName: string]: OptimisticMutationResolver;
}

A OptimisticMutationResolver receives three arguments when it's called: variables, cache, and
info.

Argument Type Description
args object The arguments that the given mutation field received.
cache Cache The cache using which data can be read or written. See Cache.
info Info Additional metadata and information about the current operation and the current field. See Info.

Read more about how to set up optimistic on the "Custom Updates"
page.

`schema` option

The schema option may be used to pass a IntrospectionQuery data to Graphcache, in other words
it's used to provide schema information to it. This schema is then used to resolve and return
partial results when querying, which are results that the cache can partially resolve as long as no
required fields are missing.

Read more about how to use the schema option on the "Schema Awareness"
page.

`storage` option

The storage option is an interface of methods that are used by the offlineExchange to persist
the cache's data to persisted storage on the user's device. it

NOTE: Offline Support is currently experimental! It hasn't been extensively tested yet and
may not always behave as expected. Please try it out with caution!

Method Type Description
writeData (delta: SerializedEntries) => Promise<void> This provided method must be able to accept an object of key-value entries that will be persisted to the storage. This method is called as a batch of updated entries becomes ready.
readData () => Promise<SerializedEntries> This provided method must be able to return a single combined object of previous key-value entries that have been previously preserved using writeData. It's only called on startup.
writeMetadata (json: SerializedRequest[]) => void This provided method must be able to persist metadata for the cache. For backwards compatibility it should be able to accept any JSON data.
readMetadata () => Promise<null | SerializedRequest[]> This provided method must be able to read the persisted metadata that has previously been written using writeMetadata. It's only called on startup.
onOnline (cb: () => void) => void This method must be able to accept a callback that is called when the user's device comes back online.
onCacheHydrated () => void This method will be called when the cacheExchange has finished hydrating the data coming from storage.

These options are split into three parts:

  • The writeMetadata and readMetadata methods are used to persist in-progress optimistic
    mutations to a storage so that they may be retried if the app has been closed while some
    optimistic mutations were still in progress.
  • The writeData and readData methods are used to persist any cache data. This is the normalized
    data that Graphcache usually keeps in memory. The cacheExchange will frequently call
    writeData with a partial object of its cache data, which readData must then be able to return
    in a single combined object on startup. We call the partial objects that writeData is called
    with "deltas".
  • The onOnline method is only used to receive a trigger that determines whether the user's device
    has come back online, which is used to retry optimistic mutations that have previously failed due
    to being offline.

The storage option may also be used with the cacheExchange instead of the offlineExchange, but
will then only use readData and writeData to persist its cache data. This is not full offline
support, but will rather be "persistence support".

Read more about how to use the storage option on the "Offline Support"
page.

Cache

An instance of the Cache interface is passed to every resolvers and updater function. It may be
used to read cached data or write cached data, which may be used in combination with the
cacheExchange configuration to alter the default behaviour of Graphcache.

keyOfEntity

The cache.keyOfEntity method may be called with a partial Data object and will return the key
for that object, or null if it's not keyable.

An object may not be keyable if it's missing the __typename or id (which falls back to _id)
fields. This method does take the keys configuration into account.

js
cache.keyOfEntity({ __typename: 'Todo', id: 1 }); // 'Todo:1'
cache.keyOfEntity({ __typename: 'Query' }); // 'Query'
cache.keyOfEntity({ __typename: 'Unknown' }); // null

There's an alternative method, cache.keyOfField which generates a key for a given field. This is
only rarely needed but similar to cache.keyOfEntity. This method accepts a field name and
optionally a field's arguments.

js
cache.keyOfField('todo'); // 'todo'
cache.keyOfField('todo', { id: 1 }); // 'todo({"id":1})'

Internally, these are the keys that records and links are stored on per entity.

resolve

This method retrieves a value or link for a given field, given a partially keyable Data object or
entity, a field name, and optionally the field's arguments. Internally this method accesses the
cache by using cache.keyOfEntity and cache.keyOfField.

js
// This may resolve a link:
cache.resolve({ __typename: 'Query' }, 'todo', { id: 1 }); // 'Todo:1'

// This may also resolve records / scalar values:
cache.resolve({ __typename: 'Todo', id: 1 }, 'id'); // 1

// You can also chain multiple calls to `cache.resolve`!
cache.resolve(cache.resolve({ __typename: 'Query' }, 'todo', { id: 1 }), 'id'); // 1

As you can see in the last example of this code snippet, the Data object can also be replaced by
an entity key, which makes it possible to pass a key from cache.keyOfEntity or another call to
cache.resolve instead of the partial entity.

Note: Because cache.resolve may return either a scalar value or another entity key, it may
be dangerous to use in some cases. It's a good idea to make sure first whether the field you're
reading will be a key or a value.

The cache.resolve method may also be called with a field key as generated by cache.keyOfField.

js
cache.resolve({ __typename: 'Query' }, cache.keyOfField('todo', { id: 1 })); // 'Todo:1'

This specialized case is likely only going to be useful in combination with
cache.inspectFields.

inspectFields

The cache.inspectFields method may be used to interrogate the cache about all available fields on
a specific entity. It accepts a partial entity or an entity key, like cache.resolve's
first argument.

When calling the method this returns an array of FieldInfo objects, one per field (including
differing arguments) that is known to the cache. The FieldInfo interface has three properties:
fieldKey, fieldName, and arguments:

Argument Type Description
fieldName string The field's name (without any arguments, just the name)
arguments object | null The field's arguments, or null if the field doesn't have any arguments
fieldKey string The field's cache key, which is similar to what cache.keyOfField would return

This works on any given entity. When calling this method the cache works in reverse on its data
structure, by parsing the entity's individual field keys.
p

js
cache.inspectFields({ __typename: 'Query' });

/*
  [
    { fieldName: 'todo', arguments: { id: 1 }, fieldKey: 'id({"id":1})' },
    { fieldName: 'todo', arguments: { id: 2 }, fieldKey: 'id({"id":2})' },
    ...
  ]
*/

readFragment

cache.readFragment accepts a GraphQL DocumentNode as the first argument and a partial entity or
an entity key as the second, like cache.resolve's first argument.

The method will then attempt to read the entity according to the fragment entirely from the cached
data. If any data is uncached and missing it'll return null.

js
import { gql } from '@urql/core';

cache.readFragment(
  gql`
    fragment _ on Todo {
      id
      text
    }
  `,
  { id: 1 }
); // Data or null

Note that the __typename may be left out on the partial entity if the fragment isn't on an
interface or union type, since in that case the __typename is already present on the fragment
itself.

If any fields on the fragment require variables, you can pass them as the third argument like so:

js
import { gql } from '@urql/core';

cache.readFragment(
  gql`
    fragment _ on User {
      id
      permissions(byGroupId: $groupId)
    }
  `,
  { id: 1 }, // this identifies the fragment (User) entity
  { groupId: 5 } // any additional field variables
);

If you need a specific fragment in a document containing multiple you can leverage
the fourth argument like this:

js
import { gql } from '@urql/core';

cache.readFragment(
  gql`
    fragment todoFields on Todo {
      id
    }

    fragment userFields on User {
      id
    }
  `,
  { id: 1 }, // this identifies the fragment (User) entity
  undefined,
  'userFields' // if not passed we take the first fragment, in this case todoFields
);

[Read more about using readFragment on the "Local Resolvers"
page.

readQuery

The cache.readQuery method is similar to cache.readFragment, but instead of reading a fragment
from cache, it reads an entire query. The only difference between how these two methods are used is
cache.readQuery's input, which is an object instead of two arguments.

The method accepts a { query, variables } object as the first argument, where query may either
be a DocumentNode or a string and variables may optionally be an object.

js
cache.readQuery({
  query: `
    query ($id: ID!) {
      todo(id: $id) { id, text }
    }
  `,
  variables: {
    id: 1
  }
); // Data or null

[Read more about using readQuery on the "Local Resolvers"
page.

Corresponding to cache.resolve, the cache.link method allows
links in the cache to be updated. While the cache.resolve method reads both
records and links from the cache, the cache.link method will only ever write
links as fragments (See cache.writeFragment below) are more
suitable for updating scalar data in the cache.

The arguments for cache.link are identical to cache.resolve and
the field's arguments are optional. However, the last argument must always be
a link, meaning null, an entity key, a keyable entity, or a list of these.

In other words, cache.link accepts an entity to write to as its first argument,
with the same arguments as cache.keyOfEntity. It then accepts one or two arguments
that are passed to cache.keyOfField to get the targeted field key. And lastly,
you may pass a list or a single entity (or an entity key).

js
// Link Query.todo field to a todo item
cache.link({ __typename: 'Query' }, 'todo', { __typename: 'Todo', id: 1 });

// You may also pass arguments instead:
cache.link({ __typename: 'Query' }, 'todo', { id: 1 }, { __typename: 'Todo', id: 1 });

// Or use entity keys instead of the entities themselves:
cache.link('Query', 'todo', cache.keyOfEntity({ __typename: 'Todo', id: 1 }));

The method may output a
warning
when any of the
entities were passed as objects but aren't keyable, which is useful when a scalar or a non-keyable
object have been passed to cache.link accidentally.

writeFragment

Corresponding to cache.readFragment, the cache.writeFragment method allows
data in the cache to be updated.

The arguments for cache.writeFragment are identical to cache.readFragment,
however the second argument, data, should not only contain properties that are necessary to derive
an entity key from the given data, but also the fields that will be written:

js
import { gql } from '@urql/core';

cache.writeFragment(
  gql`
    fragment _ on Todo {
      text
    }
  `,
  { id: 1, text: 'New Todo Text' }
);

In the example we can see that the writeFragment method returns undefined. Furthermore we pass
id in our data object so that an entity key can be written, but the fragment itself doesn't have
to include these fields.

If you need a specific fragment in a document containing multiple you can leverage
the fourth argument like this:

js
import { gql } from '@urql/core';

cache.writeFragment(
  gql`
    fragment todoFields on Todo {
      id
      text
    }

    fragment userFields on User {
      id
      name
    }
  `,
  { id: 1, name: 'New Name' }
  undefined,
  'userFields' // if not passed we take the first fragment, in this case todoFields
);

[Read more about using writeFragment on the "Custom Updates"
page.

updateQuery

Similarly to cache.writeFragment, there's an analogous method for
cache.readQuery that may be used to update query data.

The cache.updateQuery method accepts the same { query, variables } object input as its first
argument, which is the query we'd like to write to the cache. As a second argument the method
accepts an updater function. This function will be called with the query data that is already in the
cache (which may be null if the data is uncached) and must return the new data that should be
written to the cache.

js
const TodoQuery = `
  query ($id: ID!) {
    todo(id: $id) { id, text }
  }
`;

cache.updateQuery({ query: TodoQuery, variables: { id: 1 } }, data => {
  if (!data) return null;
  data.todo.text = 'New Todo Text';
  return data;
});

As we can see, our updater may return null to cancel updating any data, which we do in case the
query data is uncached.

We can also see that data can simply be mutated and doesn't have to be altered immutably. This is
because all data from the cache is already a deep copy and hence we can do to it whatever we want.

Read more about using updateQuery on the "Custom Updates"
page.

invalidate

The cache.invalidate method can be used to delete (i.e. "evict") an entity from the cache
entirely. This will cause it to disappear from all queries in Graphcache.

Its arguments are identical to cache.resolve.

Since deleting an entity will lead to some queries containing missing and uncached data, calling
invalidate may lead to additional GraphQL requests being sent, unless you're using Graphcache's
"Schema Awareness" feature
, which takes optional fields into
account.

This method accepts a partial entity or an entity key as its first argument, similar to
cache.resolve's first argument.

js
cache.invalidate({ __typename: 'Todo', id: 1 }); // Invalidates Todo:1

Additionally cache.invalidate may be used to delete specific fields only, which can be useful when
for instance a list is supposed to be evicted from cache, where a full invalidation may be
impossible. This is often the case when a field on the root Query needs to be deleted.

This method therefore accepts two additional arguments, similar to cache.resolve.

js
// Invalidates `Query.todos` with the `first: 10` argument:
cache.invalidate('Query', 'todos', { first: 10 });

Info

This is a metadata object that is passed to every resolver and updater function. It contains basic
information about the current GraphQL document and query, and also some information on the current
field that a given resolver or updater is called on.

Argument Type Description
parent Data The field's parent entity's data, as it was written or read up until now, which means it may be incomplete. Use cache.resolve to read from it.
parentTypeName string The field's parent entity's typename
parentKey string The field's parent entity's cache key (if any)
parentFieldKey string The current key's cache key, which is the parent entity's key combined with the current field's key (This is mostly obsolete)
fieldName string The current field's name
fragments { [name: string]: FragmentDefinitionNode } A dictionary of fragments from the current GraphQL document
variables object The current GraphQL operation's variables (may be an empty object)
error GraphQLError | undefined The current GraphQLError for a given field. This will always be undefined for resolvers and optimistic updaters, but may be present for updaters when the API has returned an error for a given field.
partial ?boolean This may be set to true at any point in time (by your custom resolver or by Graphcache) to indicate that some data is uncached and missing
optimistic ?boolean This is only true when an optimistic mutation update is running

Note: Using info is regarded as a last resort. Please only use information from it if
there's no other solution to get to the metadata you need. We don't regard the Info API as
stable and may change it with a simple minor version bump.

The `/extras` import

The extras subpackage is published with Graphcache and contains helpers and utilities that don't
have to be included in every app or aren't needed by all users of Graphcache.
All utilities from extras may be imported from @urql/exchange-graphcache/extras.

Currently the extras subpackage only contains the pagination resolvers that have been mentioned
on the "Computed Queries" page.

simplePagination

Accepts a single object of optional options and returns a resolver that can be inserted into the
cacheExchange's resolvers configuration.

Argument Type Description
offsetArgument ?string The field arguments' property, as passed to the resolver, that contains the current offset, i.e. the number of items to be skipped. Defaults to 'skip'.
limitArgument ?string The field arguments' property, as passed to the resolver, that contains the current page size limit, i.e. the number of items on each page. Defaults to 'limit'.
mergeMode 'after' | 'before' This option defines whether pages are merged before or after preceding ones when paginating. Defaults to 'after'.

Once set up, the resulting resolver is able to automatically concatenate all pages of a given field
automatically. Queries to this resolvers will from then on only return the infinite, combined list
of all pages.

Read more about simplePagination on the "Computed Queries"
page.

relayPagination

Accepts a single object of optional options and returns a resolver that can be inserted into the
cacheExchange's resolvers configuration.

Argument Type Description
mergeMode 'outwards' | 'inwards' With Relay pagination, pages can be queried forwards and backwards using after and before cursors. This option defines whether pages that have been queried backwards should be concatenated before (outwards) or after (inwards) all pages that have been queried forwards.

Once set up, the resulting resolver is able to automatically concatenate all pages of a given field
automatically. Queries to this resolvers will from then on only return the infinite, combined list
of all pages.

Read more about relayPagnation on the "Computed Queries"
page.

The `/default-storage` import

The default-storage subpackage is published with Graphcache and contains a default storage
interface that may be used with the storage option.

It contains the makeDefaultStorage export which is a factory function that accepts a few options
and returns a full storage interface. This storage by default persists to
IndexedDB.

Argument Type Description
idbName string The name of the IndexedDB database that is used and created if needed. By default this is set to "graphcache-v3"
maxAge number The maximum age of entries that the storage should use in whole days. By default the storage will discard entries that are older than seven days.

File: docs/api/preact.md


title: '@urql/preact' order: 2

@urql/preact

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/preact API is the same as the React urql API.
Please refer to the "urql" API docs for details on the Preact API.


File: docs/api/README.md


title: API order: 9

API

urql is a collection of multiple packages. You'll likely be using one of the framework bindings
package or exchange packages, which are all listed in this section.

Most of these packages will refer to or use utilities and types from the @urql/core package. Read
more about the core package on the "Core" page.

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.


File: docs/api/refocus-exchange.md


title: '@urql/exchange-refocus' order: 11

Refocus Exchange

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

@urql/exchange-refocus is an exchange for the urql that tracks currently active operations and redispatches them when the
window regains focus

Quick Start Guide

First install @urql/exchange-refocus alongside urql:

sh
yarn add @urql/exchange-refocus
# or
npm install --save @urql/exchange-refocus

Then add it to your Client, preferably in front of your cacheExchange

js
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { refocusExchange } from '@urql/exchange-refocus';

const client = createClient({
  url: 'http://localhost:3000/graphql',
  exchanges: [refocusExchange(), cacheExchange, fetchExchange],
});

File: docs/api/request-policy-exchange.md


title: '@urql/exchange-request-policy' order: 9

Request Policy Exchange

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/exchange-request-policy package contains an addon requestPolicyExchange for urql
that may be used to upgrade Operations' Request Policies on a
time-to-live basis.

Read more about request policies on the "Document Caching" page.

This exchange will conditionally upgrade cache-first and cache-only operations to use
cache-and-network, so that the client gets an opportunity to update its cached data, when the
operation hasn't been seen within the given ttl time. This is often preferable to setting the
default policy to cache-and-network to avoid an unnecessarily high amount of requests to be sent
to the API when switching pages.

Installation and Setup

First install @urql/exchange-request-policy alongside urql:

sh
yarn add @urql/exchange-request-policy
# or
npm install --save @urql/exchange-request-policy

Then add it to your Client, preferably in front of the cacheExchange and in front of any asynchronous
exchanges, like the fetchExchange:

js
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { requestPolicyExchange } from '@urql/exchange-request-policy';

const client = createClient({
  url: 'http://localhost:3000/graphql',
  exchanges: [
    requestPolicyExchange({
      /* config */
    }),
    cacheExchange,
    fetchExchange,
  ],
});

Options

Option Description
ttl The "time-to-live" until an Operation will be upgraded to the cache-and-network policy in milliseconds. By default 5 minutes is set.
shouldUpgrade An optional function that receives an Operation as the only argument and may return true or false depending on whether an operation should be upgraded. This can be used to filter out operations that should never be upgraded to cache-and-network.

File: docs/api/retry-exchange.md


title: '@urql/exchange-retry' order: 5

Retry Exchange

Note: These API docs are deprecated as we now keep TSDocs in all published packages.
You can view TSDocs while using these packages in your editor, as long as it supports the
TypeScript Language Server.
We're planning to replace these API docs with a separate web app soon.

The @urql/exchange-retry package contains an addon retryExchange for urql that may be used to
let failed operations be retried, typically when a previous operation has failed with a network
error.

Read more about how to use and configure the retryExchange on the "Retry Operations"
page.

Options

Option Description
initialDelayMs Specify at what interval the retrying should start, this means that if we specify 1000 that when our operation fails we'll wait 1 second and then retry it.
maxDelayMs The maximum delay between retries. The retryExchange will keep increasing the time between retries so that the server doesn't receive simultaneous requests it can't complete. This time between requests will increase with a random back-off factor applied to the initialDelayMs, read more about the thundering herd problem.
randomDelay Allows the randomized delay described above to be disabled. When this option is set to false there will be exactly a initialDelayMs wait between each retry.
maxNumberAttempts Defines the maximum number of attempts (including the initial request). For example, 2 means one retry after the initial attempt.
retryIf Apply a custom test to the returned error to determine whether it should be retried.
retryWith Apply a transform function allowing you to selectively replace a retried Operation or return a nullish value. This will act like retryIf where a truthy value retries (retryIf takes precedence and overrides this function.)