You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/source/data/defer.mdx
+42-3Lines changed: 42 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,15 +3,17 @@ title: "Using the @defer directive in Apollo Client"
3
3
description: Receive query response data incrementally
4
4
---
5
5
6
-
> ⚠️ **The `@defer` directive is currently at the [preview stage](/resources/product-launch-stages/#preview) in Apollo Client, and is available by installing `@apollo/client@latest`.** If you have feedback on it, please let us know via [GitHub issues](https://github.com/apollographql/apollo-client/issues/new?assignees=&labels=&template=bug.md).
6
+
> **The `@defer` directive is currently at the [General Availability stage](/resources/product-launch-stages/#general-availability) in Apollo Client, and is available by installing `@apollo/client@latest`.** If you have feedback on it, please let us know via [GitHub issues](https://github.com/apollographql/apollo-client/issues/new?assignees=&labels=&template=bug.md).
7
7
8
8
Beginning with version `3.7.0`, Apollo Client Web provides preview support for [the `@defer` directive](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md). This directive enables your queries to receive data for specific fields _incrementally_, instead of receiving all field data at the same time. This is helpful whenever some fields in a query take much longer to resolve than others.
9
9
10
-
> For a query to defer fields successfully, the queried endpoint must _also_ support the `@defer` directive.
10
+
> For a query to defer fields successfully, the queried endpoint must _also_ support the `@defer` directive. Entity-based `@defer` support is also at the General Availability stage in [Apollo Router](/router/executing-operations/defer-support/) and is compatible with all [federation-compatible subgraph libraries](/federation/building-supergraphs/supported-subgraphs/).
11
11
12
12
## Example
13
13
14
-
Let's say we're building a social media application that can quickly fetch a user's basic profile information, but retrieving that user's friends takes longer. If we include _all_ of those fields in a single query, we want to be able to display the profile information as soon as it's available, instead of waiting for the friend fields to resolve.
14
+
Let's say we're building a social media application that can quickly fetch a user's basic profile information, but retrieving that user's friends takes longer.
15
+
16
+
GraphQL allows us to declare all the fields our UI requires in a single query, but this also means that _our query will be as slow as the field that takes the longest to resolve_. The `@defer` directive allows us to mark parts of the query that are not necessary for our app's initial render which will be resolved once it becomes available.
15
17
16
18
To achieve this, we apply the `@defer` directive to an in-line fragment that contains all slow-resolving fields related to friend data:
Using this syntax, _if the queried server supports `@defer`,_ our client can receive the "Basic fields" in an initial response payload, followed by a supplementary payload containing the "Friend fields".
39
41
42
+
Let's look at an example in React. Here's we can assume `GET_PERSON` is the above query, `PersonQuery`, with a deferred list of friends' `id`s:
43
+
44
+
```tsx title="index.js"
45
+
import { gql, useQuery } from"@apollo/client";
46
+
47
+
function App() {
48
+
const { loading, error, data } =useQuery(GET_PERSON, {
49
+
variables: {
50
+
id: 1,
51
+
},
52
+
});
53
+
54
+
if (loading) return"Loading...";
55
+
if (error) return`Error! ${error.message}`;
56
+
57
+
return (
58
+
<>
59
+
Welcome, {data.firstName}{data.lastName}!
60
+
<details>
61
+
<summary>Friends list</summary>
62
+
{data.friends? (
63
+
<ul>
64
+
{data.friends.map((id) => (
65
+
<li>{id}</li>
66
+
))}
67
+
</ul>
68
+
) :null}
69
+
</details>
70
+
</>
71
+
);
72
+
}
73
+
```
74
+
75
+
When our call to the `useQuery` hook first resolves with an initial payload of data, `loading` will go from `true` to `false` and `firstName` and `lastName` will be populated with the values from the server. **Our deferred fields will not exist as keys on `data` yet**, so we must add conditional logic that checks for their presence. When subsequent chunks of deferred data arrive, `useQuery` will re-render (`loading` remains `false` between re-renders from deferred multipart responses) and `data` will include the deferred data as they arrive.
76
+
77
+
For this reason, `@defer` can be thought of as a tool to improve initial rendering speeds when some slower data will be displayed below the fold or offscreen. In this case, we're rendering the friends list inside a `<details>` element which is closed by default, avoiding any layout shift as the `friends` data arrives.
78
+
40
79
## Using with code generation
41
80
42
81
If you currently use [GraphQL Code Generator](https://www.the-guild.dev/graphql/codegen) for your codegen needs, note that it doesn't yet support the use of the `@defer` directive in the code output.
0 commit comments