Skip to content

Commit

Permalink
Add documentation for useSuspenseFragment (#12356)
Browse files Browse the repository at this point in the history
Co-authored-by: Maria Elisabeth Schreiber <maria.schreiber@apollographql.com>
  • Loading branch information
jerelmiller and Meschreiber authored Feb 11, 2025
1 parent 924030b commit 27e1532
Showing 1 changed file with 67 additions and 2 deletions.
69 changes: 67 additions & 2 deletions docs/source/data/fragments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ function Item(props: { item: { __typename: 'Item', id: number }}) {
const { complete, data } = useFragment({
fragment: ItemFragment,
fragmentName: "ItemFragment",
from: item
from: props.item
});

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

return <li>{complete ? data.text : "incomplete"}</li>;
Expand All @@ -589,6 +589,71 @@ function Item(props) {
See the [API reference](../api/react/hooks#usefragment) for more details on the supported options.
<MinVersion version="3.13.0">
## `useSuspenseFragment`
</MinVersion>
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.
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.
```tsx
import { useSuspenseFragment } from "@apollo/client";

function Item(props) {
const { data } = useSuspenseFragment({
fragment: ITEM_FRAGMENT,
fragmentName: "ItemFragment",
from: props.item
});

return <li>{data.text}</li>;
}
```
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:
```tsx
function List() {
const { data } = useSuspenseQuery(listQuery);

return (
<ol>
{data.list.map(item => (
<Suspense fallback={<Spinner />}>
<Item key={item.id} item={item}/>
</Suspense>
))}
</ol>
);
}
```
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`.
<Note>
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.
</Note>
### Using `useSuspenseFragment` with `@defer`
`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.
```graphql
query GetItemList {
list {
id
...ItemFragment @defer
}
}
```
Our list will now render as soon as our list returns but before the data for `ItemFragment` is loaded.
<Caution>
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.
</Caution>
<MinVersion version="3.12.0">
## Data masking
</MinVersion>
Expand Down

0 comments on commit 27e1532

Please sign in to comment.