···5151in front of all `fetchExchange`s but after all other synchronous exchanges, like the `cacheExchange`.
52525353```js
5454-import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
5454+import { Client, cacheExchange, fetchExchange } from 'urql';
5555import { authExchange } from '@urql/exchange-auth';
56565757-const client = createClient({
5757+const client = new Client({
5858 url: 'http://localhost:3000/graphql',
5959 exchanges: [
6060- dedupExchange,
6160 cacheExchange,
6261 authExchange(async utils => {
6362 return {
+29-29
docs/advanced/authoring-exchanges.md
···41414242## Using Exchanges
43434444-The `Client` accepts an `exchanges` option that defaults to the three default exchanges mentioned above. When we pass a custom list of exchanges the `Client` uses the `composeExchanges`
4545-utility, which starts chaining these exchanges.
4444+The `Client` accepts an `exchanges` option that. Initially, we may choose to just
4545+set this to two very standard exchanges — `cacheExchange` and `fetchExchange`.
46464747In essence these exchanges build a pipeline that runs in the order they're passed; _Operations_ flow
4848in from the start to the end, and _Results_ are returned through the chain in reverse.
49495050-If we look at our list of default exchanges — `dedupExchange`, `cacheExchange`, and then
5151-`fetchExchange` — an incoming operation is treated as follows:
5050+Suppose we pass the `cacheExchange` and then the `fetchExchange` to the `exchanges`.
52515353-**First,** ongoing operations are deduplicated. It wouldn't make sense to send the
5454-same operation / request twice in parallel.
5555-5656-**Second,** operations are checked against the cache. Depending on the `requestPolicy`,
5252+**First,** operations are checked against the cache. Depending on the `requestPolicy`,
5753cached results can be resolved from here instead, which would mean that the cache sends back the
5854result, and the operation doesn't travel any further in the chain.
59556060-**Third,** operations are sent to the API, and the result is turned into an `OperationResult`.
5656+**Second,** operations are sent to the API, and the result is turned into an `OperationResult`.
61576258**Lastly,** operation results then travel through the exchanges in _reverse order_, which is because
6359exchanges are a pipeline where all operations travel forward deeper into the exchange chain, and
···6561result.
66626763```js
6868-import { createClient, dedupExchange, fetchExchange, cacheExchange } from 'urql';
6464+import { Client, fetchExchange, cacheExchange } from 'urql';
69657070-const client = createClient({
6666+const client = new Client({
7167 url: 'http://localhost:3000/graphql',
7272- exchanges: [dedupExchange, cacheExchange, fetchExchange],
6868+ exchanges: [cacheExchange, fetchExchange],
7369});
7470```
75717676-We can add more exchanges to this chain, for instance, we can add the `errorExchange`, which calls a
7777-global callback whenever it sees [a `CombinedError`](../basics/errors.md) on an `OperationResult`.
7272+We can add more exchanges to this chain, for instance, we can add the `mapExchange`, which can call a
7373+callback whenever it sees [a `CombinedError`](../basics/errors.md) occur on a result.
78747975```js
8080-import { createClient, dedupExchange, fetchExchange, cacheExchange, errorExchange } from 'urql';
7676+import { Client, fetchExchange, cacheExchange, mapExchange } from 'urql';
81778282-const client = createClient({
7878+const client = new Client({
8379 url: 'http://localhost:3000/graphql',
8480 exchanges: [
8585- dedupExchange,
8681 cacheExchange,
8787- errorExchange({
8282+ mapExchange({
8883 onError(error) {
8984 console.error(error);
9085 },
···123118### Forward and Return Composition
124119125120When you create a `Client` and pass it an array of exchanges, `urql` composes them left-to-right.
126126-If we look at our previous `noopExchange` example in context, we can track what it does if it is located between the `dedupExchange` and the `fetchExchange`.
121121+If we look at our previous `noopExchange` example in context, we can track what it does if it is located between the `cacheExchange` and the `fetchExchange`.
127122128123```js
129129-import { Client, dedupExchange, fetchExchange } from 'urql';
124124+import { Client, cacheExchange, fetchExchange } from 'urql';
130125131126const noopExchange = ({ client, forward }) => {
132127 return operations$ => {
133128 // <-- The ExchangeIO function
134134- // We receive a stream of Operations from `dedupExchange` which
129129+ // We receive a stream of Operations from `cacheExchange` which
135130 // we can modify before...
136131 const forwardOperations$ = operations$;
137132···141136 const operationResult$ = forward(operations$);
142137143138 // We get back `fetchExchange`'s stream of results, which we can
144144- // also change before returning, which is what `dedupExchange`
139139+ // also change before returning, which is what `cacheExchange`
145140 // will receive when calling `forward`.
146141 return operationResult$;
147142 };
148143};
149144150145const client = new Client({
151151- exchanges: [dedupExchange, noopExchange, fetchExchange],
146146+ exchanges: [cacheExchange, noopExchange, fetchExchange],
152147});
153148```
154149···215210This why **all exchanges should be ordered synchronous first and
216211asynchronous last**.
217212218218-The default order of exchanges is:
213213+What we for instance repeat as the default setup in our docs is this:
219214220215```js
221221-import { dedupExchange, cacheExchange, fetchExchange } from 'urql';
216216+import { Client, cacheExchange, fetchExchange } from 'urql';
222217223223-[dedupExchange, cacheExchange, fetchExchange];
218218+new Client({
219219+ // ...
220220+ exchanges: [cacheExchange, fetchExchange];
221221+});
224222```
225223226226-Both the `dedupExchange` and `cacheExchange` are completely
227227-synchronous. The `fetchExchange` is asynchronous since
228228-it makes a `fetch` request and waits for a server response.
224224+The `cacheExchange` is completely synchronous.
225225+The `fetchExchange` is asynchronous since it makes a `fetch` request and waits for a server response.
226226+If we put an asynchronous exchange in front of the `cacheExchange`, that would be unexpected, and
227227+since all results would then be delayed, nothing would ever be "cached" and instead always take some
228228+amount of time to be returned.
229229230230When you're adding more exchanges, it's often crucial
231231to put them in a specific order. For instance, an authentication exchange
+4-4
docs/advanced/auto-populate-mutations.md
···2828client options.
29293030```ts
3131-import { createClient, dedupExchange, fetchExchange } from '@urql/core';
3131+import { Client, fetchExchange } from '@urql/core';
3232import { populateExchange } from '@urql/exchange-populate';
33333434-const client = createClient({
3434+const client = new Client({
3535 // ...
3636- exchanges: [dedupExchange, populateExchange({ schema }), cacheExchange, fetchExchange],
3636+ exchanges: [populateExchange({ schema }), cacheExchange, fetchExchange],
3737});
3838```
39394040The `populateExchange` should be placed in front of the `cacheExchange`, especially if you're using
4141[Graphcache](../graphcache/README.md), since it won't understand the `@populate` directive on its
4242-own. It should also be placed after the `dedupExchange` to avoid unnecessary work.
4242+own. It should also be placed in front the `cacheExchange` to avoid unnecessary work.
43434444Adding the `populateExchange` now enables us to use the `@populate` directive in our mutations.
4545
···5566# Persisted Queries and Uploads
7788-`urql` supports both [Automatic Persisted
99-Queries](https://www.apollographql.com/docs/apollo-server/performance/apq/), Persisted Queries, and
1010-[File Uploads](https://www.apollographql.com/docs/apollo-server/data/file-uploads/).
1111-1212-While File Uploads should work without any modifications, an additional exchange must be installed
1313-and added for Persisted Queries to work.
88+`urql` supports (Automatic) Persisted Queries, and File Uploads via GraphQL
99+Multipart requests. For persisted queries to work, some setup work is needed,
1010+while File Upload support is built into `@urql/core@4`.
14111512## Automatic Persisted Queries
1613···3128easier for a CDN to cache, as by default most caches would not cache POST requests automatically.
32293330In `urql`, we may use the `@urql/exchange-persisted` package's `persistedExchange` to
3434-implement Automatic Persisted Queries. This exchange works alongside the default `fetchExchange`
3535-and other exchanges by adding the `extensions.persistedQuery` parameters to a GraphQL request.
3131+enable support for Automatic Persisted Queries. This exchange works alongside other fetch or
3232+subscription exchanges by adding metadata for persisted queries to each GraphQL
3333+request by modifying the `extensions` object of operations.
36343735### Installation & Setup
3836···4543```
46444745You'll then need to add the `persistedExchange` function, that this package exposes,
4848-to your `exchanges`.
4646+to your `exchanges`, in front of exchanges that communicate with the API:
49475048```js
5151-import { createClient, dedupExchange, fetchExchange, cacheExchange } from 'urql';
5252-import { persistedExchange } from '@urql/exchange-persisted-fetch';
4949+import { Client, fetchExchange, cacheExchange } from 'urql';
5050+import { persistedExchange } from '@urql/exchange-persisted';
53515454-const client = createClient({
5252+const client = new Client({
5553 url: 'http://localhost:1234/graphql',
5654 exchanges: [
5757- dedupExchange,
5855 cacheExchange,
5956 persistedExchange({
6057 preferGetForPersistedQueries: true,
···66636764As we can see, typically it's recommended to set `preferGetForPersistedQueries` to `true` to force
6865all persisted queries to use GET requests instead of POST so that CDNs can do their job.
6969-We also added the `persistedExchange` in front of the usual `fetchExchange`, since it has to
7070-update operations before they reach an exchange that talks to an API.
6666+It does so by setting the `preferGetMethod` option to `'force'` when it's
6767+updating operations.
71687272-The `preferGetForPersistedQueries` is similar to the [`Client`'s
7373-`preferGetMethod`](../api/core.md#client) but only switches persisted queries to use GET requests
7474-instead. This is preferable since sometimes the GraphQL query can grow too large for a simple GET
7575-query to handle, while the `persistedExchange`'s SHA256 hashes will remain predictably small.
6969+The `fetchExchange` can see the modifications that the `persistedExchange` is
7070+making to operations, and understands to leave out the `query` from any request
7171+as needed. The same should be happening to the `subscriptionExchange`, if you're
7272+using it for queries.
76737774### Customizing Hashing
7875···8986second argument, a GraphQL `DocumentNode` object.
90879188```js
9292-persistedFetchExchange({
8989+persistedExchange({
9390 generateHash: (_, document) => document.documentId,
9491});
9592```
···10198```js
10299import sha256 from 'hash.js/lib/hash/sha/256';
103100104104-persistedFetchExchange({
105105- generateHash: async query => {
101101+persistedExchange({
102102+ async generateHash(query) {
106103 return sha256().update(query).digest('hex');
107104 },
108105});
···115112116113## File Uploads
117114118118-Many GraphQL server frameworks and APIs support the ["GraphQL Multipart Request
119119-Spec](https://github.com/jaydenseric/graphql-multipart-request-spec) to allow files to be uploaded.
120120-Often, this is defined in schemas using a `File` or `Upload` input.
121121-This allows us to pass a `File` or `Blob` directly to our GraphQL requests as variables, and the
122122-spec requires us to perform this request as a multipart upload.
115115+GraphQL server APIs commonly support the [GraphQL Multipart Request
116116+spec](https://github.com/jaydenseric/graphql-multipart-request-spec) to allow for File Uploads
117117+directly with a GraphQL API.
123118124124-Files are often handled in the browser via the [File API](https://developer.mozilla.org/en-US/docs/Web/API/File),
125125-which we may typically get to via a [file input](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications)
119119+If a GraphQL API supports this, we can pass a [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File)
120120+or a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) directly into our variables and
121121+define the corresponding scalar for our variable, which is often called `File` or `Upload`.
122122+123123+In a browser, the `File` object may often be retrieved via a
124124+[file input](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications),
126125for example.
127126128128-In `urql`, these are supported natively, so as long as your JS environment supports either `File` or
129129-`Blob`s, you can pass these directly to any `urql` API via your `variables`, and the default
130130-`fetchExchange` will swich to using a multipart request instead.
127127+The `@urql/core@4` package supports File Uploads natively, so we won't have to do any installation
128128+or setup work. When `urql` sees a `File` or a `Blob` anywhere in your `variables`, it switches to
129129+a `multipart/form-data` request, converts the request to a `FormData` object, according to the
130130+GraphQL Multipart Request specification, and sends it off to the API.
131131132132-Previously, this worked by installing the [`@urql/multipart-fetch-exchange` package](../api/multipart-fetch-exchange.md),
133133-however, this package has been deprecated and file uploads are now built into `@urql/core`.
132132+> **Note:** Previously, this worked by installing the `@urql/multipart-fetch-exchange` package.
133133+> however, this package has been deprecated and file uploads are now built into `@urql/core@4`.
+5-7
docs/advanced/retry-operations.md
···2222You'll then need to add the `retryExchange`, exposed by this package, to your `urql` Client:
23232424```js
2525-import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
2525+import { Client, cacheExchange, fetchExchange } from 'urql';
2626import { retryExchange } from '@urql/exchange-retry';
27272828// None of these options have to be added, these are the default values.
···36363737// Note the position of the retryExchange - it should be placed prior to the
3838// fetchExchange and after the cacheExchange for it to function correctly
3939-const client = createClient({
3939+const client = new Client({
4040 url: 'http://localhost:1234/graphql',
4141 exchanges: [
4242- dedupExchange,
4342 cacheExchange,
4443 retryExchange(options), // Use the retryExchange factory to add a new exchange
4544 fetchExchange,
···6968let's look at an example:
70697170```js
7272-import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
7171+import { Client, cacheExchange, fetchExchange } from 'urql';
7372import { retryExchange } from '@urql/exchange-retry';
74737575-const client = createClient({
7474+const client = new Client({
7675 url: 'http://localhost:1234/graphql',
7776 exchanges: [
7878- dedupExchange,
7977 cacheExchange,
8078 retryExchange({
8179 retryIf: error => {
8282- return !!(error.graphQLErrors.length > 0 || error.networkError);
8080+ return !!(error.graphQLErrors.length > 0 || error.networkError);
8381 },
8482 }),
8583 fetchExchange,
+6-7
docs/advanced/server-side-rendering.md
···1818To start out with the `ssrExchange` we have to add the exchange to our `Client`:
19192020```js
2121-import { createClient, dedupExchange, cacheExchange, fetchExchange, ssrExchange } from '@urql/core';
2121+import { Client, cacheExchange, fetchExchange, ssrExchange } from '@urql/core';
22222323const isServerSide = typeof window === 'undefined';
2424···2828 initialState: !isServerSide ? window.__URQL_DATA__ : undefined,
2929});
30303131-const client = createClient({
3131+const client = new Client({
3232 exchanges: [
3333- dedupExchange,
3433 cacheExchange,
3534 ssr, // Add `ssr` in front of the `fetchExchange`
3635 fetchExchange,
···113112import prepass from 'react-ssr-prepass';
114113115114import {
116116- createClient,
117117- dedupExchange,
115115+ Client,
118116 cacheExchange,
119117 fetchExchange,
120118 ssrExchange,
···125123 // ...
126124 const ssr = ssrExchange({ isClient: false });
127125128128- const client createClient({
126126+ const client new Client({
127127+ url: 'https://??',
129128 suspense: true, // This activates urql's Suspense mode on the server-side
130130- exchanges: [dedupExchange, cacheExchange, ssr, fetchExchange]
129129+ exchanges: [cacheExchange, ssr, fetchExchange]
131130 });
132131133132 const element = (
+13-18
docs/advanced/subscriptions.md
···1313To add support for subscriptions we need to add the `subscriptionExchange` to our `Client`.
14141515```js
1616-import { Client, dedupExchange, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';
1616+import { Client, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';
17171818const client = new Client({
1919 url: 'http://localhost:3000/graphql',
2020 exchanges: [
2121- dedupExchange,
2221 cacheExchange,
2322 fetchExchange,
2423 subscriptionExchange({
···4746For backends supporting `graphql-ws`, we recommend using the [graphql-ws](https://github.com/enisdenjo/graphql-ws) client.
48474948```js
5050-import { createClient, dedupExchange, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';
4949+import { Client, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';
5150import { createClient as createWSClient } from 'graphql-ws';
52515352const wsClient = createWSClient({
5453 url: 'ws://localhost/graphql',
5554});
56555757-const client = createClient({
5656+const client = new Client({
5857 url: '/graphql',
5958 exchanges: [
6060- dedupExchange,
6159 cacheExchange,
6260 fetchExchange,
6361 subscriptionExchange({
···8583> The `subscriptions-transport-ws` package isn't actively maintained. If your API supports the new protocol or you can swap the package out, consider using [`graphql-ws`](#setting-up-graphql-ws) instead.
86848785```js
8888-import { Client, dedupExchange, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';
8686+import { Client, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';
8987import { SubscriptionClient } from 'subscriptions-transport-ws';
90889189const subscriptionClient = new SubscriptionClient('ws://localhost/graphql', { reconnect: true });
···9391const client = new Client({
9492 url: '/graphql',
9593 exchanges: [
9696- dedupExchange,
9794 cacheExchange,
9895 fetchExchange,
9996 subscriptionExchange({
···195192 from
196193 text
197194 }
198198- }`
199199- });
195195+ }
196196+ `,
197197+ });
200198</script>
201199202200{#if !$messages.data}
···267265 text
268266 }
269267 }
270270- `
268268+ `,
271269 }, handleSubscription)
272270273271 return {
···298296use subscriptions in a Node.js environment.
299297300298```js
301301-import { pipe, subscribe } from 'wonka';
299299+import { gql } from '@urql/core';
302300303303-const MessageSub = `
301301+const MessageSub = gql`
304302 subscription MessageSub {
305303 newMessages {
306304 id
···310308 }
311309`;
312310313313-const { unsubscribe } = pipe(
314314- client.subscription(MessageSub),
315315- subscribe(result => {
316316- console.log(result); // { data: ... }
317317- })
318318-);
311311+const { unsubscribe } = client.subscription(MessageSub).subscribe(result => {
312312+ console.log(result); // { data: ... }
313313+});
319314```
+5-1
docs/api/README.md
···1111Most of these packages will refer to or use utilities and types from the `@urql/core` package. [Read
1212more about the core package on the "Core" page.](../basics/core.md)
13131414+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
1515+> You can view TSDocs while using these packages in your editor, as long as it supports the
1616+> TypeScript Language Server.
1717+> We're planning to replace these API docs with a separate web app soon.
1818+1419- [`@urql/core` API docs](./core.md)
1520- [`urql` React API docs](./urql.md)
1621- [`@urql/preact` Preact API docs](./preact.md)
···1823- [`@urql/exchange-graphcache` API docs](./graphcache.md)
1924- [`@urql/exchange-retry` API docs](./retry-exchange.md)
2025- [`@urql/exchange-execute` API docs](./execute-exchange.md)
2121-- [`@urql/exchange-multipart-fetch` API docs](./multipart-fetch-exchange.md)
2226- [`@urql/exchange-request-policy` API docs](./request-policy-exchange.md)
2327- [`@urql/exchange-auth` API docs](./auth-exchange.md)
2428- [`@urql/exchange-refocus` API docs](./refocus-exchange.md)
+5
docs/api/auth-exchange.md
···5566# Authentication Exchange
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/exchange-auth` package contains an addon `authExchange` for `urql` that aims to make it
914easy to implement complex authentication and reauthentication flows as are typically found with JWT
1015token based API authentication.
+6-1
docs/api/core.md
···5566# @urql/core
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/core` package is the basis of all framework bindings. Each bindings-package,
914like [`urql` for React](./urql.md) or [`@urql/preact`](./preact.md), will reuse the core logic and
1015reexport all exports from `@urql/core`.
···22272328| Input | Type | Description |
2429| ----------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2525-| `exchanges` | `Exchange[]` | An array of `Exchange`s that the client should use |
3030+| `exchanges` | `Exchange[]` | An array of `Exchange`s that the client should use |
2631| `url` | `string` | The GraphQL API URL as used by `fetchExchange` |
2732| `fetchOptions` | `RequestInit \| () => RequestInit` | Additional `fetchOptions` that `fetch` in `fetchExchange` should use to make a request |
2833| `fetch` | `typeof fetch` | An alternative implementation of `fetch` that will be used by the `fetchExchange` instead of `window.fetch` |
+5
docs/api/execute-exchange.md
···5566# Execute Exchange
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/exchange-execute` package contains an addon `executeExchange` for `urql` that may be used to
914execute queries against a local schema. It is therefore a drop-in replacement for the default
1015_fetchExchange_ and useful for the server-side, debugging, or testing.
+5
docs/api/graphcache.md
···5566# @urql/exchange-graphcache
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/exchange-graphcache` package contains an addon `cacheExchange` for `urql` that may be
914used to replace the default [`cacheExchange`](./core.md#cacheexchange), which switches `urql` from
1015using ["Document Caching"](../basics/document-caching.md) to ["Normalized
-46
docs/api/multipart-fetch-exchange.md
···11----
22-title: '@urql/exchange-multipart-fetch'
33-order: 7
44----
55-66-# Multipart Fetch Exchange
77-88-> **Deprecation**: The `multipartFetchExchange` has been deprecated, and
99-> `@urql/core` now supports GraphQL Multipart Requests natively. This won't
1010-> break the behaviour of your existing apps, however, it's recommended to remove
1111-> the `multipartFetchExchange` from your apps.
1212-1313-The `@urql/exchange-multipart-fetch` package contains an addon `multipartFetchExchange` for `urql`
1414-that enables file uploads via `multipart/form-data` POST requests.
1515-1616-It follows the unofficial [GraphQL Multipart Request
1717-Spec](https://github.com/jaydenseric/graphql-multipart-request-spec) which is supported by the
1818-[Apollo Sever package](https://www.apollographql.com/docs/apollo-server/data/file-uploads/).
1919-2020-This exchange uses the same fetch logic as the [`fetchExchange`](./core.md#fetchexchange) and by reusing logic from `@urql/core/internal`.
2121-The `multipartFetchExchange` is a drop-in replacement for the default
2222-[`fetchExchange`](./core.md#fetchexchange) and will act exactly like the `fetchExchange` unless the
2323-`variables` that it receives for mutations contain any `File`s as detected by the `extract-files` package.
2424-2525-## Installation and Setup
2626-2727-First install `@urql/exchange-multipart-fetch` alongside `urql`:
2828-2929-```sh
3030-yarn add @urql/exchange-multipart-fetch
3131-# or
3232-npm install --save @urql/exchange-multipart-fetch
3333-```
3434-3535-The `multipartFetchExchange` is a drop-in replacement for the `fetchExchange`, which should be
3636-replaced in the list of `exchanges`:
3737-3838-```js
3939-import { createClient, dedupExchange, cacheExchange } from 'urql';
4040-import { multipartFetchExchange } from '@urql/exchange-multipart-fetch';
4141-4242-const client = createClient({
4343- url: 'http://localhost:3000/graphql',
4444- exchanges: [dedupExchange, cacheExchange, multipartFetchExchange],
4545-});
4646-```
+5
docs/api/preact.md
···5566# @urql/preact
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/preact` API is the same as the React `urql` API.
914Please refer to [the "urql" API docs](./urql.md) for details on the Preact API.
+5
docs/api/refocus-exchange.md
···5566# Refocus Exchange
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813`@urql/exchange-refocus` is an exchange for the `urql` that tracks currently active operations and redispatches them when the
914window regains focus
1015
+5
docs/api/request-policy-exchange.md
···5566# Request Policy Exchange
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/exchange-request-policy` package contains an addon `requestPolicyExchange` for `urql`
914that may be used to upgrade [Operations' Request Policies](./core.md#requestpolicy) on a
1015time-to-live basis.
+5
docs/api/retry-exchange.md
···5566# Retry Exchange
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813The `@urql/exchange-retry` package contains an addon `retryExchange` for `urql` that may be used to
914let failed operations be retried, typically when a previous operation has failed with a network
1015error.
+5
docs/api/svelte.md
···5566# Svelte API
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813## queryStore
9141015The `queryStore` factory accepts properties as inputs and returns a Svelte pausable, readable store
+12-7
docs/api/urql.md
···5566# React API
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813## useQuery
9141015Accepts a single required options object as an input with the following properties:
···1419| `query` | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. |
1520| `variables` | `?object` | The variables to be used with the GraphQL request. |
1621| `requestPolicy` | `?RequestPolicy` | An optional [request policy](./core.md#requestpolicy) that should be used specifying the cache strategy. |
1717-| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |
2222+| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |
1823| `context` | `?object` | Holds the contextual information for the query. |
19242025This hook returns a tuple of the shape `[result, executeQuery]`.
···46514752Accepts a single required options object as an input with the following properties:
48534949-| Prop | Type | Description |
5050-| ---------------------------------------------------- | ------------------------ | ---------------------------------------------------------------------------------- |
5151-| `query` | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. |
5252-| `variables` | `?object` | The variables to be used with the GraphQL request. |
5353-| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |
5454-| `context` | `?object` | Holds the contextual information for the query. |
5454+| Prop | Type | Description |
5555+| ----------- | ------------------------ | ------------------------------------------------------------------------------------------------ |
5656+| `query` | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. |
5757+| `variables` | `?object` | The variables to be used with the GraphQL request. |
5858+| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |
5959+| `context` | `?object` | Holds the contextual information for the query. |
55605661The hook optionally accepts a second argument, which may be a handler function with a type signature
5762of:
+5
docs/api/vue.md
···5566# Vue API
7788+> **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
99+> You can view TSDocs while using these packages in your editor, as long as it supports the
1010+> TypeScript Language Server.
1111+> We're planning to replace these API docs with a separate web app soon.
1212+813## useQuery
9141015Accepts a single required options object as an input with the following properties:
+110-91
docs/architecture.md
···5566# Architecture
7788-`urql` is a highly customizable and flexible GraphQL client, that happens to come with some default
99-[core behavior in the core package](./basics/core.md).
88+`urql` is a highly customizable and flexible GraphQL client.
99+As you use it in your app, it's split into three parts:
1010+1111+- Bindings — such as for React, Preact, Vue, or Svelte — which interact with `@urql/core`'s
1212+ `Client`.
1313+- The Client — as created [with the core `@urql/core` package](./basics/code.md), which interacts with "exchanges" to execute GraphQL
1414+ operations, and which you can also use directly.
1515+- Exchanges, which provide functionality like fetching or caching to the `Client`.
10161117By default, `urql` aims to provide the minimal amount of features that allow us to build an app
1218quickly. However, `urql` has also been designed to be a GraphQL Client
···3440## Requests and Operations on the Client
35413642If `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us
3737-defining queries or mutations. Any GraphQL request can be abstracted into their query documents and
3838-their variables. In `urql`, these GraphQL requests are treated as unique objects, which are uniquely
3939-identified by the query document and variables (which is why a `key` is generated from the two). This
4040-`key` is a hash number of the query document and variables and uniquely identifies our
4141-[`GraphQLRequest`](./api/core.md#graphqlrequest).
4343+defining queries or mutations by writing in GraphQL's query language.
4444+4545+Any GraphQL request can be abstracted into its query documents and its variables.
4646+4747+```js
4848+import { gql } from '@urql/core';
4949+5050+const query = gql`
5151+ query($name: String!) {
5252+ helloWorld(name: $name)
5353+ }
5454+`;
5555+5656+const request = createRequest(query, {
5757+ name: 'Urkel',
5858+});
5959+```
6060+6161+In `urql`, these GraphQL requests are treated as unique objects and each GraphQL request will have
6262+a `key` generated for them. This `key` is a hash of the query document and the variables you provide
6363+and are set on the `key` property of a [`GraphQLRequest`](./api/core.md#graphqlrequest).
42644343-Whenever we decide to send a request to our API we start by using `urql`'s
4444-[`Client`](./api/core.md#client). It accepts several options like `url` or `requestPolicy` which are
4545-extra information on how the GraphQL requests are executed.
6565+Whenever we decide to send our GraphQL requests to a GraphQL API we start by using `urql`'s
6666+[`Client`](./api/core.md#client).
6767+The `Client` accepts several options to configure its behaviour and the behaviour of exchanges,
6868+like the `fetchExchange`. For instance, we can pass it a `url` which the `fetchExchange` will
6969+use to make a `fetch` call to our GraphQL API.
46704771```js
4848-import { Client, dedupExchange, cacheExchange, fetchExchange } from '@urql/core';
7272+import { Client, cacheExchange, fetchExchange } from '@urql/core';
49735050-new Client({
7474+const client = new Client({
5175 url: 'http://localhost:3000/graphql',
5252- requestPolicy: 'cache-first',
5353- exchanges: [dedupExchange, cacheExchange, fetchExchange]
7676+ exchanges: [cacheExchange, fetchExchange],
5477});
5578```
56795757-The bindings that we've seen in [the "Basics" section](./basics/README.md) interact with [the
5858-`Client`](./api/core.md#client) directly and are a thin abstraction on top of it. Though some methods can be called on it directly, as seen [on the "Core Usage"
8080+Above, we're defining a `Client` that is ready to accept our requests. It will apply basic
8181+document caching and will send uncached requests to the `url` we pass it.
8282+The bindings that we've seen in [the "Basics" section](./basics/README.md), like `useQuery` for
8383+React for example, interact with [the `Client`](./api/core.md#client) directly and are a thin
8484+abstraction.
8585+8686+Some methods can be called on it directly however, as seen [on the "Core Usage"
5987page](./basics/core.md#one-off-queries-and-mutations).
60886161-When we send our queries or mutations to the `Client`, internally they will be managed as
6262-[`Operation`](./api/core.md#operation)s. An "Operation" is an extension of `GraphQLRequest`s. Not
6363-only do they carry the `query`, `variables`, and a `key` property, they will also identify the
6464-`kind` of operation that is executed, like `"query"` or `"mutation"`. We can also find the
6565-`Client`'s options on `operation.context` which carries an operation's metadata.
8989+```js
9090+// Given our request and client defined above, we can call
9191+const subscription = client.executeQuery(request).subscribe(result => {
9292+ console.log(result.data);
9393+});
9494+```
9595+9696+As we've seen, `urql` defines our query documents and variables as
9797+[`GraphQLRequest`s](./api/core.md#graphqlrequest). However, since we have more metadata that is
9898+needed, like our `url` option on the `Client`, `urql` internally creates [`Operation`s](./api/core.md#operation)
9999+each time a request is executed. The operations are then forwarded to the exchanges, like the
100100+`cacheExchange` and `fetchExchange`.
101101+102102+An "Operation" is an extension of `GraphQLRequest`s. Not only do they carry the `query`, `variables`,
103103+and a `key` property, they will also identify the `kind` of operation that is executed, like
104104+`"query"` or `"mutation"`, and they contain the `Client`'s options on `operation.context`.
6610567106
681076969-It's the `Client`s responsibility to accept an `Operation` and execute it. The bindings internally
7070-call the `client.executeQuery`, `client.executeMutation`, or `client.executeSubscription` methods,
7171-and we'll get a "stream" of results. This "stream" allows us to register a callback with it to
7272-receive results.
108108+This means, once we hand over a GraphQL request to the `Client`, it will create an `Operation`,
109109+and then hand it over to the exchanges until a result comes back.
731107474-In the diagram we can see that each operation is a signal for our request to start at which point
7575-we can expect to receive our results eventually on a callback. Once we're not interested in results
7676-anymore a special "teardown" signal is issued on the `Client`. While we don't see operations outside
7777-the `Client`, they're what travel through the "Exchanges" on the `Client`.
111111+As shown in the diagram, each operation is like an event or signal for a GraphQL request to start,
112112+and the exchanges will eventually send back a corresponding result.
113113+However, because the cache can send updates to us whenever it detects a change, or you could cancel
114114+a GraphQL request before it finishes, a special "teardown" `Operation` also exists, which cancels
115115+ongoing requests.
7811679117## The Client and Exchanges
8011881119To reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the
82120`Client`, but we never see the operations that are created in the background from our bindings. We
83121call a method like `client.executeQuery` (or it's called for us in the bindings), an operation is
8484-issued internally when we subscribe with a callback, and later our callback is called with results.
122122+issued internally when we subscribe with a callback, and later, we're given results.
8512386124
87125···126164127165### The Exchanges
128166129129-The default set of exchanges that `@urql/core` contains and applies to a `Client` are:
167167+By default, the `Client` doesn't do anything with GraphQL requests. It contains only the logic to
168168+manage and differentiate between active and inactive requests and converts them to operations.
169169+To actually do something with our GraphQL requests, it needs _exchanges_, which are like plugins
170170+that you can pass to create a pipeline of how GraphQL operations are executed.
171171+172172+By default, you may want to add the `cacheExchange` and the `fetchExchange` from `@urql/core`:
130173131131-- `dedupExchange`: Deduplicates pending operations (pending = waiting for a result)
132132-- `cacheExchange`: The default caching logic with ["Document Caching"](./basics/document-caching.md)
133133-- `fetchExchange`: Sends an operation to the API using `fetch` and adds results to the output stream
174174+- `cacheExchange`: Caches GraphQL results with ["Document Caching"](./basics/document-caching.md)
175175+- `fetchExchange`: Executes GraphQL requests with a `fetch` HTTP call
134176135135-When we don't pass the `exchanges` option manually to our `Client` then these are the ones that will
136136-be applied. As we can see, an exchange exerts a lot of power over our operations and results. They
137137-determine a lot of the logic of the `Client`, taking care of things like deduplication, caching, and
138138-sending requests to our API.
177177+```js
178178+import { Client, cacheExchange, fetchExchange } from '@urql/core';
139179140140-Some of the exchanges that are available to us are:
180180+const client = new Client({
181181+ url: 'http://localhost:3000/graphql',
182182+ exchanges: [cacheExchange, fetchExchange],
183183+});
184184+```
141185142142-- [`mapExchange`](./api/core.md#mapexchange): Allows reacting to operations, results, and errors
186186+As we can tell, exchanges define not only how GraphQL requests are executed and handled, but also
187187+get control over caching. Exchanges can be used to change almost any behaviour in the `Client`,
188188+although internally they only handle incoming & outgoing requests and incoming & outgoing results.
189189+190190+Some more exchanges that we can use with our `Client` are:
191191+192192+- [`mapExchange`](./api/core.md#mapexchange): Allows changing and reacting to operations, results, and errors
143193- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to
144194 collect results for client-side rehydration.
145145-- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried
146146-- [`multipartFetchExchange`](./advanced/persistence-and-uploads.md#file-uploads): Provides multipart file upload capability
195195+- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried on errors
147196- [`persistedFetchExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic
148197 Persisted Queries
149149-- [`authExchange`](./advanced/authentication.md): Allows complex authentication flows to be implemented
150150- easily.
151151-- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically upgrades `cache-only` and `cache-first` operations to `cache-and-network` after a given amount of time.
152152-- [`refocusExchange`](./api/refocus-exchange.md): Tracks open queries and refetches them
153153- when the window regains focus.
198198+- [`authExchange`](./advanced/authentication.md): Allows refresh authentication to be implemented easily.
199199+- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically refreshes results given a TTL.
154200- `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/urql-graphql/urql-devtools)
155201156202We can even swap out our [document cache](./basics/document-caching.md), which is implemented by
···182228directly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams
183229and will have to deal with their API.
184230185185-### The Wonka library
186186-187187-`urql` utilises the [Wonka](https://github.com/kitten/wonka) library for its streams. It has a
188188-few advantages that are specifically tailored for the `urql` library and ecosystem:
189189-190190-- It is extremely lightweight and treeshakeable, with a size of around 3.7kB minzipped.
191191-- It's cross-platform and cross-language compatible, having been written in
192192- [Reason](https://reasonml.github.io/) and provides support for [Flow](https://flow.org/)
193193- and [TypeScript](https://www.typescriptlang.org/v2/).
194194-- It's a predictable and iterable toolchain, emitting synchronous events whenever possible.
195195-196196-Typical usage of Wonka will involve creating a _source_ of some values and a _sink_.
197197-198198-```js
199199-import { fromArray, map, subscribe, pipe } from 'wonka';
200200-201201-const { unsubscribe } = pipe(
202202- fromArray([1, 2, 3]),
203203- map(x => x * 2),
204204- subscribe(x => {
205205- console.log(x); // 2, 4, 6
206206- })
207207-);
208208-```
209209-210210-In Wonka, like with Observables, streams are cancellable by calling the `unsubscribe` method that a
211211-subscription returns.
212212-213213-[Read more about Wonka in its documentation](https://wonka.kitten.sh/basics/background).
214214-215231### Stream patterns with the client
216232217233When we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery)
218218-or [`client.query`](./api/core.md#clientquery) then these will return a Wonka stream. Those are
219219-essentially just a bunch of callbacks.
234234+or [`client.query`](./api/core.md#clientquery) then these will return a "stream" of results.
220235221221-We can use [`wonka`'s `subscribe`](https://wonka.kitten.sh/api/sinks#subscribe) function to start
222222-this stream. We pass this function a callback and will receive results back from the `Client`, as it
223223-starts our operation. When we unsubscribe then the `Client` will stop this operation by sending a
224224-special "teardown" operation to our exchanges.
236236+It's normal for GraphQL subscriptions to deliver multiple results, however, even GraphQL queries can
237237+give you multiple results in `urql`. This is because operations influence one another. When a cache
238238+invalidates a query, this query may refetch, and a new result is delivered to your application.
239239+240240+Multiple results mean that once you subscribe to a GraphQL query via the `Client`, you may receive
241241+new results in the future.
225242226243```js
227227-import { pipe, subscribe } from 'wonka';
244244+import { gql } from '@urql/core';
228245229229-const QUERY = `
246246+const QUERY = gql`
230247 query Test($id: ID!) {
231248 getUser(id: $id) {
232249 id
···235252 }
236253`;
237254238238-const { unsubscribe } = pipe(
239239- client.query(QUERY, { id: 'test' }),
240240- subscribe(result => {
241241- console.log(result); // { data: ... }
242242- })
243243-);
255255+client.query(QUERY, { id: 'test' }).subscribe(result => {
256256+ console.log(result); // { data: ... }
257257+});
244258```
245259246260Read more about the available APIs on the `Client` in the [Core API docs](./api/core.md).
261261+262262+Internally, these streams and all exchanges are written using a library called
263263+[`wonka`](https://wonka.kitten.sh/basics/background), which is a tiny Observable-like
264264+library. It is used to write exchanges and when we interact with the `Client` it is used internally
265265+as well.
+56-32
docs/basics/core.md
···2727`@urql/core` or use it standalone, e.g. in a Node.js environment.
28282929```sh
3030-yarn add @urql/core graphql
3030+yarn add @urql/core
3131# or
3232-npm install --save @urql/core graphql
3232+npm install --save @urql/core
3333```
34343535Since all bindings and all exchanges depend on `@urql/core`, we may sometimes run into problems
···3939deduplicating our dependencies.
40404141```sh
4242+# npm
4343+npm dedupe
4444+# pnpm
4545+pnpm dedupe
4646+# yarn
4247npx yarn-deduplicate && yarn
4343-# or
4444-npm dedupe
4548```
46494750## GraphQL Tags
···130133131134### Setting up the `Client`
132135133133-The `@urql/core` package exports a function called `createClient` which we can use to
136136+The `@urql/core` package exports a `Client` class, which we can use to
134137create the GraphQL client. This central `Client` manages all of our GraphQL requests and results.
135138136139```js
137137-import { createClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/core';
140140+import { Client, cacheExchange, fetchExchange } from '@urql/core';
138141139139-const client = createClient({
142142+const client = new Client({
140143 url: 'http://localhost:3000/graphql',
141141- exchanges: [dedupExchange, cacheExchange, fetchExchange],
144144+ exchanges: [cacheExchange, fetchExchange],
142145});
143146```
144147145145-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.
148148+At the bare minimum we'll need to pass an API's `url`, and the `fetchExchange`,
149149+when we create a `Client` to get started.
146150147151Another common option is `fetchOptions`. This option allows us to customize the options that will be
148152passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object, or
···152156GraphQL API.
153157154158```js
155155-const client = createClient({
159159+const client = new Client({
156160 url: 'http://localhost:3000/graphql',
157157- exchanges: [dedupExchange, cacheExchange, fetchExchange],
161161+ exchanges: [cacheExchange, fetchExchange],
158162 fetchOptions: () => {
159163 const token = getToken();
160164 return {
···166170167171### The `Client`s options
168172169169-As we've seen above, the most important option for the `Client` is `url`, since it won't work
170170-without it. However, another important option on the `Client` is the `exchanges` option.
173173+As we've seen above, the most important options for the `Client` are `url` and `exchanges`.
174174+The `url` option is used by the `fetchExchange` to send GraphQL requests to an API.
171175172172-This option passes a list of exchanges to the `Client`, which tell it how to execute our requests
173173-and how to cache data in a certain order.
176176+The `exchanges` option is of particular importance however because it tells the `Client` what to do
177177+with our GraphQL requests:
174178175179```js
176176-import { createClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/core';
180180+import { Client, cacheExchange, fetchExchange } from '@urql/core';
177181178178-const client = createClient({
182182+const client = new Client({
179183 url: 'http://localhost:3000/graphql',
180180- exchanges: [dedupExchange, cacheExchange, fetchExchange],
184184+ exchanges: [cacheExchange, fetchExchange],
181185});
182186```
183187188188+For instance, here, the `Client`'s caching and fetching features are only available because we're
189189+passing it exchanges. In the above example, the `Client` will try to first read a GraphQL request
190190+from a local cache, and if this request isn't cached it'll make an HTTP request.
191191+The caching in `urql` is also implemented as an exchange, so for instance, the behavior described
192192+on the ["Document Caching" page](./document-caching.md) is all contained within the `cacheExchange`
193193+above.
194194+184195Later, [in the "Advanced" section](../advanced/README.md) we'll see many more features that `urql`
185196supports by adding new exchanges to this list. On [the "Architecture" page](../architecture.md)
186197we'll also learn more about what exchanges are and why they exist.
187187-188188-For now, it's enough for us to know that our requests are executed using the logic in the
189189-exchanges in order. First, the `dedupExchange` deduplicates requests if we send the same queries
190190-twice, the `cacheExchange` implements the default "document caching" behaviour (as we'll learn about
191191-on the ["Document Caching"](./document-caching.md) page), and lastly the `fetchExchange` is
192192-responsible for sending our requests to our GraphQL API.
193198194199### One-off Queries and Mutations
195200···220225result as a promise. This may be useful when we don't plan on cancelling queries, or we don't
221226care about future updates to this data and are just looking to query a result once.
222227228228+This can also be written using async/await by simply awaiting the return value of `client.query`:
229229+230230+```js
231231+const QUERY = `
232232+ query Test($id: ID!) {
233233+ getUser(id: $id) {
234234+ id
235235+ name
236236+ }
237237+ }
238238+`;
239239+240240+async function query() {
241241+ const result = await client.query(QUERY, { id: 'test' });
242242+ console.log(result); // { data: ... }
243243+}
244244+```
245245+223246The same can be done for mutations by calling the `client.mutation` method instead of the
224247`client.query` method.
248248+249249+It's worth noting that promisifying a query result will always only give us _one_ result, because
250250+we're not calling `subscribe`. This means that we'll never see cache updates when we're asking for
251251+a single result like we do above.
252252+253253+#### Reading only cache data
225254226255Similarly there's a way to read data from the cache synchronously, provided that the cache has
227256received a result for a given query before. The `Client` has a `readQuery` method, which is a
···258287somewhere else then we'll get notified of the new API result as well, as long as we're subscribed.
259288260289```js
261261-import { pipe, subscribe } from 'wonka';
262262-263290const QUERY = `
264291 query Test($id: ID!) {
265292 getUser(id: $id) {
···269296 }
270297`;
271298272272-const { unsubscribe } = pipe(
273273- client.query(QUERY, { id: 'test' }),
274274- subscribe(result => {
275275- console.log(result); // { data: ... }
276276- })
277277-);
299299+const { unsubscribe } = client.query(QUERY, { id: 'test' }).subscribe(result => {
300300+ console.log(result); // { data: ... }
301301+});
278302```
279303280304This code example is similar to the one before. However, instead of sending a one-off query, we're
+21-21
docs/basics/react-preact.md
···1818with at first. We'll install the package with our package manager of choice.
19192020```sh
2121-yarn add urql graphql
2121+yarn add urql
2222# or
2323-npm install --save urql graphql
2323+npm install --save urql
2424```
25252626To use `urql` with Preact, we have to install `@urql/preact` instead of `urql` and import from
···37373838### Setting up the `Client`
39394040-The `urql` and `@urql/preact` packages export a method called `createClient` which we can use to
4040+The `urql` and `@urql/preact` packages export a `Client` class, which we can use to
4141create the GraphQL client. This central `Client` manages all of our GraphQL requests and results.
42424343```js
4444-import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
4444+import { Client, cacheExchange, fetchExchange } from 'urql';
45454646-const client = createClient({
4646+const client = new Client({
4747 url: 'http://localhost:3000/graphql',
4848- exchanges: [dedupExchange, cacheExchange, fetchExchange],
4848+ exchanges: [cacheExchange, fetchExchange],
4949});
5050```
51515252-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.
5252+At the bare minimum we'll need to pass an API's `url` and `exchanges` when we create a `Client`
5353+to get started.
53545455Another common option is `fetchOptions`. This option allows us to customize the options that will be
5556passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object, or
···5960GraphQL API.
60616162```js
6262-const client = createClient({
6363+const client = new Client({
6364 url: 'http://localhost:3000/graphql',
6464- exchanges: [dedupExchange, cacheExchange, fetchExchange],
6565+ exchanges: [cacheExchange, fetchExchange],
6566 fetchOptions: () => {
6667 const token = getToken();
6768 return {
···7879the `Provider` export.
79808081```jsx
8181-import { createClient, Provider, dedupExchange, cacheExchange, fetchExchange } from 'urql';
8282+import { Client, Provider, cacheExchange, fetchExchange } from 'urql';
82838383-const client = createClient({
8484+const client = new Client({
8485 url: 'http://localhost:3000/graphql',
8585- exchanges: [dedupExchange, cacheExchange, fetchExchange],
8686+ exchanges: [cacheExchange, fetchExchange],
8687});
87888889const App = () => (
···107108todo items. Let's dive right into it!
108109109110```jsx
110110-import { useQuery } from 'urql';
111111+import { gql, useQuery } from 'urql';
111112112112-const TodosQuery = `
113113+const TodosQuery = gql`
113114 query {
114115 todos {
115116 id
···154155to supply variables to our query.
155156156157```jsx
157157-const TodosListQuery = `
158158+const TodosListQuery = gql`
158159 query ($from: Int!, $limit: Int!) {
159159- todos (from: $from, limit: $limit) {
160160+ todos(from: $from, limit: $limit) {
160161 id
161162 title
162163 }
···198199199200```jsx
200201const Todos = ({ from, limit }) => {
201201- const shouldPause = from === undefined || from === null ||
202202- limit === undefined || limit === null;
202202+ const shouldPause = from === undefined || from === null || limit === undefined || limit === null;
203203 const [result, reexecuteQuery] = useQuery({
204204 query: TodosListQuery,
205205 variables: { from, limit },
···244244we may also change the `Client`'s default `requestPolicy` by passing it there.
245245246246```js
247247-import { createClient } from 'urql';
247247+import { Client, cacheExchange, fetchExchange } from 'urql';
248248249249-const client = createClient({
249249+const client = new Client({
250250 url: 'http://localhost:3000/graphql',
251251- exchanges: [dedupExchange, cacheExchange, fetchExchange],
251251+ exchanges: [cacheExchange, fetchExchange],
252252 // every operation will by default use cache-and-network rather
253253 // than cache-first now:
254254 requestPolicy: 'cache-and-network',
+17-16
docs/basics/svelte.md
···1717Installing `@urql/svelte` is quick and no other packages are immediately necessary.
18181919```sh
2020-yarn add @urql/svelte graphql
2020+yarn add @urql/svelte
2121# or
2222-npm install --save @urql/svelte graphql
2222+npm install --save @urql/svelte
2323```
24242525Most libraries related to GraphQL also need the `graphql` package to be installed as a peer
···44444545### Setting up the `Client`
46464747-The `@urql/svelte` package exports a method called `createClient` which we can use to create
4747+The `@urql/svelte` package exports a `Client` class, which we can use to create
4848the GraphQL client. This central `Client` manages all of our GraphQL requests and results.
49495050```js
5151-import { createClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/svelte';
5151+import { Client, cacheExchange, fetchExchange } from '@urql/svelte';
52525353-const client = createClient({
5353+const client = new Client({
5454 url: 'http://localhost:3000/graphql',
5555- exchanges: [dedupExchange, cacheExchange, fetchExchange],
5555+ exchanges: [cacheExchange, fetchExchange],
5656});
5757```
58585959-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.
5959+At the bare minimum we'll need to pass an API's `url` and `exchanges`
6060+when we create a `Client` to get started.
60616162Another common option is `fetchOptions`. This option allows us to customize the options that will be
6263passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or
···6667GraphQL API.
67686869```js
6969-const client = createClient({
7070+const client = new Client({
7071 url: 'http://localhost:3000/graphql',
7171- exchanges: [dedupExchange, cacheExchange, fetchExchange],
7272+ exchanges: [cacheExchange, fetchExchange],
7273 fetchOptions: () => {
7374 const token = getToken();
7475 return {
···87888889```html
8990<script>
9090- import { createClient, setContextClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/svelte';
9191+ import { Client, setContextClient, cacheExchange, fetchExchange } from '@urql/svelte';
91929292- const client = createClient({
9393+ const client = new Client({
9394 url: 'http://localhost:3000/graphql',
9494- exchanges: [dedupExchange, cacheExchange, fetchExchange],
9595+ exchanges: [cacheExchange, fetchExchange],
9596 });
96979798 setContextClient(client);
···291292we may also change the `Client`'s default `requestPolicy` by passing it there.
292293293294```js
294294-import { createClient } from '@urql/svelte';
295295+import { Client, cacheExchange, fetchExchange } from '@urql/svelte';
295296296296-const client = createClient({
297297+const client = new Client({
297298 url: 'http://localhost:3000/graphql',
298298- exchanges: [dedupExchange, cacheExchange, fetchExchange],
299299+ exchanges: [cacheExchange, fetchExchange],
299300 // every operation will by default use cache-and-network rather
300301 // than cache-first now:
301302 requestPolicy: 'cache-and-network',
···400401 result = mutationStore({
401402 client,
402403 query: gql`
403403- mutation($id: ID!, $title: String!) {
404404+ mutation ($id: ID!, $title: String!) {
404405 updateTodo(id: $id, title: $title) {
405406 id
406407 title
+6-5
docs/basics/typescript-integration.md
···1414To get and running, install the following packages:
15151616```sh
1717-yarn add graphql
1818-yarn add -D typescript @graphql-codegen/cli @graphql-codegen/client-preset
1717+yarn add -D graphql typescript @graphql-codegen/cli @graphql-codegen/client-preset
1918# or
2020-npm install graphql
2121-npm install -D typescript @graphql-codegen/cli @graphql-codegen/client-preset
1919+npm install -D graphql typescript @graphql-codegen/cli @graphql-codegen/client-preset
2220```
23212422Then, add the following script to your `package.json`:
···140138141139function App() {
142140 // `data` is typed!
143143- const [{ data }] = useQuery({ query: allFilmsWithVariablesQueryDocument, variables: { first: 10 } });
141141+ const [{ data }] = useQuery({
142142+ query: allFilmsWithVariablesQueryDocument,
143143+ variables: { first: 10 },
144144+ });
144145 return (
145146 <div className="App">
146147 {data && (
+3-3
docs/basics/ui-patterns.md
···169169else our requests will never get upgraded.
170170171171```js
172172-import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
172172+import { Client, cacheExchange, fetchExchange } from 'urql';
173173import { refocusExchange } from '@urql/exchange-refocus';
174174175175-const client = createClient({
175175+const client = new Client({
176176 url: 'some-url',
177177- exchanges: [dedupExchange, refocusExchange(), cacheExchange, fetchExchange],
177177+ exchanges: [refocusExchange(), cacheExchange, fetchExchange],
178178});
179179```
180180
+42-41
docs/basics/vue.md
···33333434### Setting up the `Client`
35353636-The `@urql/vue` package exports a method called `createClient` which we can use to create
3636+The `@urql/vue` package exports a `Client` class, which we can use to create
3737the GraphQL client. This central `Client` manages all of our GraphQL requests and results.
38383939```js
4040-import { createClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/vue';
4040+import { Client, cacheExchange, fetchExchange } from '@urql/vue';
41414242-const client = createClient({
4242+const client = new Client({
4343 url: 'http://localhost:3000/graphql',
4444- exchanges: [dedupExchange, cacheExchange, fetchExchange],
4444+ exchanges: [cacheExchange, fetchExchange],
4545});
4646```
47474848-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.
4848+At the bare minimum we'll need to pass an API's `url` and `exchanges` when we create a `Client`
4949+to get started.
49505051Another common option is `fetchOptions`. This option allows us to customize the options that will be
5152passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or
···5556GraphQL API.
56575758```js
5858-const client = createClient({
5959+const client = new Client({
5960 url: 'http://localhost:3000/graphql',
6060- exchanges: [dedupExchange, cacheExchange, fetchExchange],
6161+ exchanges: [cacheExchange, fetchExchange],
6162 fetchOptions: () => {
6263 const token = getToken();
6364 return {
···75767677The first method is to use `@urql/vue`'s `provideClient` function. This must be called in any of
7778your parent components and accepts either a `Client` directly or just the options that you'd pass to
7878-`createClient`.
7979+`Client`.
79808081```html
8182<script>
8282- import { createClient, provideClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/vue';
8383+ import { Client, provideClient, cacheExchange, fetchExchange } from '@urql/vue';
83848484- const client = createClient({
8585+ const client = new Client({
8586 url: 'http://localhost:3000/graphql',
8686- exchanges: [dedupExchange, cacheExchange, fetchExchange],
8787+ exchanges: [cacheExchange, fetchExchange],
8788 });
88898990 provideClient(client);
···107108app.mount('#app');
108109```
109110110110-The plugin also accepts `createClient`'s options or a `Client` as its inputs.
111111+The plugin also accepts `Client`'s options or a `Client` as its inputs.
111112112113## Queries
113114···134135</template>
135136136137<script>
137137-import { useQuery } from '@urql/vue';
138138+import { gql, useQuery } from '@urql/vue';
138139139140export default {
140141 setup() {
141142 const result = useQuery({
142142- query: `
143143+ query: gql`
143144 {
144145 todos {
145146 id
···184185</template>
185186186187<script>
187187-import { useQuery } from '@urql/vue';
188188+import { gql, useQuery } from '@urql/vue';
188189189190export default {
190191 props: ['from', 'limit'],
191192 setup({ from, limit }) {
192193 return useQuery({
193193- query: `
194194+ query: gql`
194195 query ($from: Int!, $limit: Int!) {
195196 todos(from: $from, limit: $limit) {
196197 id
···221222</template>
222223223224<script>
224224-import { useQuery } from '@urql/vue';
225225+import { gql, useQuery } from '@urql/vue';
225226226227export default {
227228 setup() {
228229 const from = ref(0);
229230230231 const result = useQuery({
231231- query: `
232232+ query: gql`
232233 query ($from: Int!, $limit: Int!) {
233234 todos(from: $from, limit: $limit) {
234235 id
···266267267268```js
268269import { reactive } from 'vue'
269269-import { useQuery } from '@urql/vue';
270270+import { gql, useQuery } from '@urql/vue';
270271271272export default {
272273 props: ['from', 'limit'],
273274 setup({ from, limit }) {
274275 const shouldPause = computed(() => from == null || limit == null);
275276 return useQuery({
276276- query: `
277277+ query: gql`
277278 query ($from: Int!, $limit: Int!) {
278279 todos(from: $from, limit: $limit) {
279280 id
···307308</template>
308309309310<script>
310310-import { useQuery } from '@urql/vue';
311311+import { gql, useQuery } from '@urql/vue';
311312312313export default {
313314 setup() {
314315 return useQuery({
315315- query: `
316316+ query: gql`
316317 {
317318 todos {
318319 id
···364365we may also change the `Client`'s default `requestPolicy` by passing it there.
365366366367```js
367367-import { createClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/vue';
368368+import { Client, cacheExchange, fetchExchange } from '@urql/vue';
368369369369-const client = createClient({
370370+const client = new Client({
370371 url: 'http://localhost:3000/graphql',
371371- exchanges: [dedupExchange, cacheExchange, fetchExchange],
372372+ exchanges: [cacheExchange, fetchExchange],
372373 // every operation will by default use cache-and-network rather
373374 // than cache-first now:
374375 requestPolicy: 'cache-and-network',
···415416`requestPolicy` of our query just once and set it to `network-only` to skip the cache.
416417417418```js
418418-import { useQuery } from '@urql/vue';
419419+import { gql, useQuery } from '@urql/vue';
419420420421export default {
421422 setup() {
422423 const result = useQuery({
423423- query: `
424424+ query: gql`
424425 {
425426 todos {
426427 id
···473474</template>
474475475476<script>
476476-import { useQuery } from '@urql/vue';
477477+import { gql, useQuery } from '@urql/vue';
477478478479export default {
479480 async setup() {
480481 const { data, error } = await useQuery({
481481- query: `
482482+ query: gql`
482483 {
483484 todos {
484485 id
···580581example! We'll set up a mutation that _updates_ a todo item's title.
581582582583```js
583583-import { useMutation } from '@urql/vue';
584584+import { gql, useMutation } from '@urql/vue';
584585585586export default {
586587 setup() {
587587- const { executeMutation: updateTodo } = useMutation(`
588588- mutation ($id: ID!, $title: String!) {
589589- updateTodo (id: $id, title: $title) {
588588+ const { executeMutation: updateTodo } = useMutation(gql`
589589+ mutation($id: ID!, $title: String!) {
590590+ updateTodo(id: $id, title: $title) {
590591 id
591592 title
592593 }
···616617`executeMutation` method returns when it's called:
617618618619```js
619619-import { useMutation } from '@urql/vue';
620620+import { gql, useMutation } from '@urql/vue';
620621621622export default {
622623 setup() {
623623- const updateTodoResult = useMutation(`
624624- mutation ($id: ID!, $title: String!) {
625625- updateTodo (id: $id, title: $title) {
624624+ const updateTodoResult = useMutation(gql`
625625+ mutation($id: ID!, $title: String!) {
626626+ updateTodo(id: $id, title: $title) {
626627 id
627628 title
628629 }
···657658[Read more about errors on our "Errors" page.](./errors.md)
658659659660```js
660660-import { useMutation } from '@urql/vue';
661661+import { gql, useMutation } from '@urql/vue';
661662662663export default {
663664 setup() {
664664- const updateTodoResult = useMutation(`
665665- mutation ($id: ID!, $title: String!) {
666666- updateTodo (id: $id, title: $title) {
665665+ const updateTodoResult = useMutation(gql`
666666+ mutation($id: ID!, $title: String!) {
667667+ updateTodo(id: $id, title: $title) {
667668 id
668669 title
669670 }
+46-47
docs/comparison.md
···35353636### Core Features
37373838-| | urql | Apollo | Relay |
3939-| ------------------------------------------ | ---------------------------------- | -------------------------------------------------------------------------- | ------------------------------ |
4040-| Extensible on a network level | ✅ Exchanges | ✅ Links | ✅ Network Layers |
4141-| Extensible on a cache / control flow level | ✅ Exchanges | 🛑 | 🛑 |
4242-| Base Bundle Size | **5.9kB** (7.1kB with bindings) | 32.9kB | 27.7kB (34.1kB with bindings) |
4343-| Devtools | ✅ | ✅ | ✅ |
4444-| Subscriptions | ✅ | ✅ | ✅ |
4545-| Client-side Rehydration | ✅ | ✅ | ✅ |
4646-| Polled Queries | 🔶 | ✅ | ✅ |
4747-| Lazy Queries | ✅ | ✅ | ✅ |
4848-| Stale while Revalidate / Cache and Network | ✅ | ✅ | ✅ |
4949-| Focus Refetching | ✅ `@urql/exchange-refocus` | 🛑 | 🛑 |
5050-| Stale Time Configuration | ✅ `@urql/exchange-request-policy` | ✅ | 🛑 |
5151-| Persisted Queries | ✅ `@urql/exchange-persisted` | ✅ `apollo-link-persisted-queries` | ✅ |
5252-| Batched Queries | 🛑 | ✅ `apollo-link-batch-http` | 🟡 `react-relay-network-layer` |
5353-| Live Queries | 🛑 | 🛑 | ✅ |
5454-| Defer & Stream Directives | ✅ | ✅ / 🛑 (`@defer` is supported in >=3.7.0, `@stream` is not yet supported) | 🟡 (unreleased) |
5555-| Switching to `GET` method | ✅ | ✅ | 🟡 `react-relay-network-layer` |
5656-| File Uploads | ✅ | 🟡 `apollo-upload-client` | 🛑 |
5757-| Retrying Failed Queries | ✅ `@urql/exchange-retry` | ✅ `apollo-link-retry` | ✅ `DefaultNetworkLayer` |
5858-| Easy Authentication Flows | ✅ `@urql/exchange-auth` | 🛑 (no docs for refresh-based authentication) | 🟡 `react-relay-network-layer` |
5959-| Automatic Refetch after Mutation | ✅ (with document cache) | 🛑 | ✅ |
3838+| | urql | Apollo | Relay |
3939+| ------------------------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
4040+| Extensible on a network level | ✅ Exchanges | ✅ Links | ✅ Network Layers |
4141+| Extensible on a cache / control flow level | ✅ Exchanges | 🛑 | 🛑 |
4242+| Base Bundle Size | **10kB** (11kB with bindings) | ~50kB (55kB with React hooks) | 45kB (66kB with bindings) |
4343+| Devtools | ✅ | ✅ | ✅ |
4444+| Subscriptions | 🔶 [Docs](./advanced/subscriptions.md) | 🔶 [Docs](https://www.apollographql.com/docs/react/data/subscriptions/#setting-up-the-transport) | 🔶 [Docs](https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions/#configuring-the-network-layer) |
4545+| Client-side Rehydration | ✅ [Docs](./advanced/server-side-rendering.md) | ✅ [Docs](https://www.apollographql.com/docs/react/performance/server-side-rendering) | 🛑 |
4646+| Polled Queries | 🔶 | ✅ | ✅ |
4747+| Lazy Queries | ✅ | ✅ | ✅ |
4848+| Stale while Revalidate / Cache and Network | ✅ | ✅ | ✅ |
4949+| Focus Refetching | ✅ `@urql/exchange-refocus` | 🛑 | 🛑 |
5050+| Stale Time Configuration | ✅ `@urql/exchange-request-policy` | ✅ | 🛑 |
5151+| Persisted Queries | ✅ `@urql/exchange-persisted` | ✅ `apollo-link-persisted-queries` | 🔶 |
5252+| Batched Queries | 🛑 | ✅ `apollo-link-batch-http` | 🟡 `react-relay-network-layer` |
5353+| Live Queries | ✅ (via Incremental Delivery) | 🛑 | ✅ |
5454+| Defer & Stream Directives | ✅ | ✅ / 🛑 (`@defer` is supported in >=3.7.0, `@stream` is not yet supported) | 🟡 (unreleased) |
5555+| Switching to `GET` method | ✅ | ✅ | 🟡 `react-relay-network-layer` |
5656+| File Uploads | ✅ | 🟡 `apollo-upload-client` | 🛑 |
5757+| Retrying Failed Queries | ✅ `@urql/exchange-retry` | ✅ `apollo-link-retry` | ✅ `DefaultNetworkLayer` |
5858+| Easy Authentication Flows | ✅ `@urql/exchange-auth` | 🛑 (no docs for refresh-based authentication) | 🟡 `react-relay-network-layer` |
5959+| Automatic Refetch after Mutation | ✅ (with document cache) | 🛑 | ✅ |
60606161Typically these are all additional addon features that you may expect from a GraphQL client, no
6262matter which framework you use it with. It's worth mentioning that all three clients support some
···8282| | urql | Apollo | Relay |
8383| ------------------------------ | -------------- | ------------------- | ------------------ |
8484| React Bindings | ✅ | ✅ | ✅ |
8585-| React Concurrent Hooks Support | ✅ | 🛑 | ✅ (experimental) |
8686-| React Legacy Hooks Support | ✅ | ✅ | 🟡 `relay-hooks` |
8787-| React Suspense (Experimental) | ✅ | 🛑 | ✅ |
8585+| React Concurrent Hooks Support | ✅ | ✅ | ✅ |
8686+| React Suspense | ✅ | 🛑 | ✅ |
8887| Next.js Integration | ✅ `next-urql` | 🟡 | 🔶 |
8988| Preact Support | ✅ | 🔶 | 🔶 |
9089| Svelte Bindings | ✅ | 🟡 `svelte-apollo` | 🟡 `svelte-relay` |
···94939594### Caching and State
96959797-| | urql | Apollo | Relay |
9898-| ------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------- | ---------------------------------------------- |
9999-| Caching Strategy | Document Caching, Normalized Caching with `@urql/exchange-graphcache` | Normalized Caching | Normalized Caching (schema restrictions apply) |
100100-| Added Bundle Size | +6.5kB (with Graphcache) | +0 (default) | +0 (default) |
101101-| Automatic Garbage Collection | ✅ | 🔶 | ✅ |
102102-| Local State Management | 🛑 | ✅ | ✅ |
103103-| Pagination Support | 🔶 | 🔶 | ✅ |
104104-| Optimistic Updates | ✅ | ✅ | ✅ |
105105-| Local Updates | ✅ | ✅ | ✅ |
106106-| Out-of-band Cache Updates | 🛑 (stays true to server data) | ✅ | ✅ |
107107-| Local Resolvers and Redirects | ✅ | ✅ | 🛑 (not needed) |
108108-| Complex Resolvers (nested non-normalized return values) | ✅ | 🛑 | 🛑 (not needed) |
109109-| Commutativity Guarantees | ✅ | 🛑 | ✅ |
110110-| Partial Results | ✅ | ✅ | 🛑 |
111111-| Safe Partial Results (schema-based) | ✅ | 🛑 | 🛑 |
112112-| Persistence Support | ✅ | ✅ `apollo-cache-persist` | 🟡 `@wora/relay-store` |
113113-| Offline Support | ✅ | 🛑 | 🟡 `@wora/relay-offline` |
9696+| | urql | Apollo | Relay |
9797+| ------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------- |
9898+| Caching Strategy | Document Caching, Normalized Caching with `@urql/exchange-graphcache` | Normalized Caching | Normalized Caching (schema restrictions apply) |
9999+| Added Bundle Size | +8kB (with Graphcache) | +0 (default) | +0 (default) |
100100+| Automatic Garbage Collection | ✅ | 🔶 | ✅ |
101101+| Local State Management | 🛑 | ✅ | ✅ |
102102+| Pagination Support | 🔶 | 🔶 | ✅ |
103103+| Optimistic Updates | ✅ | ✅ | ✅ |
104104+| Local Updates | ✅ | ✅ | ✅ |
105105+| Out-of-band Cache Updates | 🛑 (stays true to server data) | ✅ | ✅ |
106106+| Local Resolvers and Redirects | ✅ | ✅ | 🛑 |
107107+| Complex Resolvers (nested non-normalized return values) | ✅ | 🛑 | 🛑 |
108108+| Commutativity Guarantees | ✅ | 🛑 | ✅ |
109109+| Partial Results | ✅ | ✅ | 🛑 |
110110+| Safe Partial Results (schema-based) | ✅ | 🔶 (experimental via `useFragment`) | 🛑 |
111111+| Persistence Support | ✅ | ✅ `apollo-cache-persist` | 🟡 `@wora/relay-store` |
112112+| Offline Support | ✅ | 🛑 | 🟡 `@wora/relay-offline` |
114113115114`urql` is the only of the three clients that doesn't pick [normalized
116115caching](./graphcache/normalized-caching.md) as its default caching strategy. Typically this is seen
···145144but often this comparison is hard to make. When you start comparing bundle sizes of these three
146145GraphQL clients you should keep in mind that:
147146148148-- Parts of the `graphql` package tree-shake away and may also be replaced (e.g. `parse`)
149149-- All packages in `urql` reuse parts of `@urql/core` and `wonka`, which means adding all their total
147147+- Some dependencies may be external and the above sizes listed are total minified+gzipped sizes
148148+ - `@urql/core` imports from `wonka` for stream utilities and `@0no-co/graphql.web` for GraphQL query
149149+ language utilities
150150+ - Other GraphQL clients may import other exernal dependencies.
151151+- All `urql` packages reuse parts of `@urql/core` and `wonka`, which means adding all their total
150152 sizes up doesn't give you a correct result of their total expected bundle size.
151151-- These sizes may change drastically given the code you write and add yourself, but can be managed
152152- via precompilation (e.g. with `babel-plugin-graphql-tag` or GraphQL Code Generator for Apollo and
153153- `urql`)
+3-3
docs/graphcache/README.md
···7070without passing any options.
71717272```js
7373-import { createClient, dedupExchange, fetchExchange } from 'urql';
7373+import { Client, fetchExchange } from 'urql';
7474import { cacheExchange } from '@urql/exchange-graphcache';
75757676-const client = createClient({
7676+const client = new Client({
7777 url: 'http://localhost:3000/graphql',
7878- exchanges: [dedupExchange, cacheExchange({}), fetchExchange],
7878+ exchanges: [cacheExchange({}), fetchExchange],
7979});
8080```
8181
+6-6
docs/graphcache/offline.md
···3232`offlineExchange` that's also exported by `@urql/exchange-graphcache`.
33333434```js
3535-import { createClient, dedupExchange, fetchExchange } from 'urql';
3535+import { Client, fetchExchange } from 'urql';
3636import { offlineExchange } from '@urql/exchange-graphcache';
37373838const cache = offlineExchange({
···4545 },
4646});
47474848-const client = createClient({
4848+const client = new Client({
4949 url: 'http://localhost:3000/graphql',
5050- exchanges: [dedupExchange, cache, fetchExchange],
5050+ exchanges: [cache, fetchExchange],
5151});
5252```
5353···6161function from `@urql/exchange-graphcache/default-storage`.
62626363```js
6464-import { createClient, dedupExchange, fetchExchange } from 'urql';
6464+import { Client, fetchExchange } from 'urql';
6565import { offlineExchange } from '@urql/exchange-graphcache';
6666import { makeDefaultStorage } from '@urql/exchange-graphcache/default-storage';
6767···8181 },
8282});
83838484-const client = createClient({
8484+const client = new Client({
8585 url: 'http://localhost:3000/graphql',
8686- exchanges: [dedupExchange, cache, fetchExchange],
8686+ exchanges: [cache, fetchExchange],
8787});
8888```
8989