Skip to content

Commit 27e1532

Browse files
Add documentation for useSuspenseFragment (#12356)
Co-authored-by: Maria Elisabeth Schreiber <[email protected]>
1 parent 924030b commit 27e1532

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

docs/source/data/fragments.mdx

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ function Item(props: { item: { __typename: 'Item', id: number }}) {
561561
const { complete, data } = useFragment({
562562
fragment: ItemFragment,
563563
fragmentName: "ItemFragment",
564-
from: item
564+
from: props.item
565565
});
566566

567567
return <li>{complete ? data.text : "incomplete"}</li>;
@@ -573,7 +573,7 @@ function Item(props) {
573573
const { complete, data } = useFragment({
574574
fragment: ITEM_FRAGMENT,
575575
fragmentName: "ItemFragment",
576-
from: item
576+
from: props.item
577577
});
578578

579579
return <li>{complete ? data.text : "incomplete"}</li>;
@@ -589,6 +589,71 @@ function Item(props) {
589589
590590
See the [API reference](../api/react/hooks#usefragment) for more details on the supported options.
591591
592+
<MinVersion version="3.13.0">
593+
## `useSuspenseFragment`
594+
</MinVersion>
595+
596+
For those that have integrated with React [Suspense](https://react.dev/reference/react/Suspense), `useSuspenseFragment` is available as a drop-in replacement for `useFragment`. `useSuspenseFragment` works identically to `useFragment` but will suspend while `data` is incomplete.
597+
598+
Let's update the example from the previous section to use `useSuspenseFragment`. First, we'll update our `Item` component and replace `useFragment` with `useSuspenseFragment`. Since we are using Suspense, we no longer have to check for a `complete` property to determine if the result is complete because the component will suspend otherwise.
599+
600+
```tsx
601+
import { useSuspenseFragment } from "@apollo/client";
602+
603+
function Item(props) {
604+
const { data } = useSuspenseFragment({
605+
fragment: ITEM_FRAGMENT,
606+
fragmentName: "ItemFragment",
607+
from: props.item
608+
});
609+
610+
return <li>{data.text}</li>;
611+
}
612+
```
613+
614+
Next, we'll will wrap our `Item` components in a `Suspense` boundary to show a loading indicator if the data from `ItemFragment` is not complete. Since we're using Suspense, we'll replace `useQuery` with `useSuspenseQuery` as well:
615+
616+
```tsx
617+
function List() {
618+
const { data } = useSuspenseQuery(listQuery);
619+
620+
return (
621+
<ol>
622+
{data.list.map(item => (
623+
<Suspense fallback={<Spinner />}>
624+
<Item key={item.id} item={item}/>
625+
</Suspense>
626+
))}
627+
</ol>
628+
);
629+
}
630+
```
631+
632+
And that's it! Suspense made our `Item` component a bit more succinct since we no longer need to check the `complete` property to determine if we can safely use `data`.
633+
634+
<Note>
635+
In most cases, `useSuspenseFragment` will not suspend when rendered as a child of a query component. In this example `useSuspenseQuery` loads the full query data before each `Item` is rendered so the `data` inside each fragment is already complete. The `Suspense` boundary in this example ensures that a loading spinner is shown if field data is removed for any given item in the list in the cache, such as when a manual cache update is performed.
636+
</Note>
637+
638+
### Using `useSuspenseFragment` with `@defer`
639+
640+
`useSuspenseFragment` is helpful when combined with the [`@defer` directive](./directives#defer) to show a loading state while the fragment data is streamed to the query. Let's update our `GetItemList` query to defer loading the `ItemFragment`'s fields.
641+
642+
```graphql
643+
query GetItemList {
644+
list {
645+
id
646+
...ItemFragment @defer
647+
}
648+
}
649+
```
650+
651+
Our list will now render as soon as our list returns but before the data for `ItemFragment` is loaded.
652+
653+
<Caution>
654+
You **must** ensure that any key fields used to identify the object passed to the `from` option are not deferred. If they are, you risk suspending the `useSuspenseFragment` hook forever. If you need to defer loading key fields, conditionally render the component until the object passed to the `from` option is identifiable by the cache.
655+
</Caution>
656+
592657
<MinVersion version="3.12.0">
593658
## Data masking
594659
</MinVersion>

0 commit comments

Comments
 (0)