-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Documentation for observeFragment and waitForFragmentData
Reviewed By: tyao1 Differential Revision: D63400528 fbshipit-source-id: f737d8da9ba6c13669aa6746c4e2a6beffe8e573
- Loading branch information
1 parent
6a038d0
commit 36eecfe
Showing
3 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
86 changes: 86 additions & 0 deletions
86
website/docs/api-reference/relay-runtime/observe-fragment.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
--- | ||
id: observe-fragment | ||
title: observeFragment | ||
slug: api-reference/observe-fragment | ||
description: Read the value of a fragment and observe it's state and value over time | ||
keywords: | ||
- observable | ||
- fragment | ||
--- | ||
|
||
import DocsRating from '@site/src/core/DocsRating'; | ||
|
||
:::warning | ||
`observeFragment` is still an experimental API. It currently has some limitations and may evolve slightly during this phase. | ||
::: | ||
|
||
## `observeFragment` | ||
|
||
In some cases it can be useful to define data that you wish to read using a GraphQL fragment, but then consume it outside of React render function. `observeFragment` allows you to consume the state and value of a fragment as it changes over time. This includes loading and error states as well as changes to the data as it gets updated by local updates, mutations or updates to Relay's normalized store from other queries. | ||
|
||
To read a fragment's data just once, see [`waitForFragmentData`](./wait-for-fragment-data.md). | ||
|
||
### Example | ||
|
||
```ts | ||
import {observeFragment} from "relay-runtime/experimental"; | ||
import { useEffect } from "react"; | ||
import { useFragment } from "react-relay"; | ||
import { graphql } from "relay-runtime"; | ||
|
||
function MyComponent({ key }) { | ||
const user = useFragment( | ||
graphql` | ||
fragment UserFragment on User { | ||
...TitleFragment | ||
} | ||
`, | ||
key, | ||
); | ||
|
||
// Update the title as the user's name changes without triggering rerenders. | ||
useEffect(() => { | ||
const subscription = observeFragment( | ||
graphql` | ||
fragment TitleFragment on User { | ||
name | ||
} | ||
`, | ||
user, | ||
).subscribe(result => { | ||
switch(result.kind) { | ||
case "loading": | ||
window.title = "...loading"; | ||
break; | ||
case "error": | ||
window.title = "Oops, we hit an error"; | ||
break; | ||
case "ok": | ||
window.title = `Welcome ${result.value.name}`; | ||
break; | ||
} | ||
}); | ||
return () => { | ||
subscription.unsubscribe(); | ||
}; | ||
}, [user]); | ||
|
||
return <div>Check out the document title!</div>; | ||
} | ||
``` | ||
|
||
### Arguments | ||
|
||
* `environment`: `IEnvironment`. A Relay environment. | ||
* `fragment`: GraphQL fragment specified using a `graphql` template literal. | ||
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from. | ||
* The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared. | ||
|
||
### Return Value | ||
|
||
* An [`Observable`](../../glossary/glossary.md#observable) which returns a discriminated union modeling the three possible states in which a fragment's data might be: | ||
* `{state: 'ok', value: T}` - When data is avalaible the state is `'ok'`. `T` is the data defined in the fragment. | ||
* `{state: 'error': error: Error}` - When the fragment is in an error state either due to network level errors, [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.md) or [`@required(action: THROW)`](../../guides/required-directive.md) field errors. | ||
* `{state: 'loading'}` - When the parent request, or current `@defer` payload is still in flight, or a [`@live` Relay Resolver](../../guides/relay-resolvers/live-fields.md) being read is in a suspended state. | ||
|
||
<DocsRating /> |
89 changes: 89 additions & 0 deletions
89
website/docs/api-reference/relay-runtime/wait-for-fragment-data.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
--- | ||
id: wait-for-fragment-data | ||
title: waitForFragmentData | ||
slug: /api-reference/wait-for-fragment-data/ | ||
description: Read the value of a fragment as a promise | ||
keywords: | ||
- promise | ||
- fragment | ||
--- | ||
|
||
import DocsRating from '@site/src/core/DocsRating'; | ||
|
||
:::warning | ||
`waitForFragmentData` is still an experimental API. It currently has some limitations and may evolve slightly during this phase. | ||
::: | ||
|
||
## `waitForFragmentData` | ||
|
||
In some cases it can be useful to define data that you wish to read using a GraphQL fragment, but then consume it just once outside of React render function. `waitForFragmentData` allows you to wait for the data of a fragment to be avalaible, | ||
|
||
To read a fragment's data as it changes over time, see [`observeFragment`](./observe-fragment.md). | ||
|
||
### Example: Deferring data used in an event handler | ||
|
||
One use case for `waitForFragmentData` is to defer fetching data that is needed inside an event handler, but is not needed to render the initial view. | ||
|
||
```tsx | ||
import { useCallback } from "react"; | ||
import { useFragment } from "react-relay"; | ||
import { graphql } from "relay-runtime"; | ||
import { waitForFragmentData } from "relay-runtime/experimental"; | ||
|
||
function MyComponent({ key }) { | ||
const user = useFragment( | ||
graphql` | ||
fragment UserFragment on User { | ||
name | ||
# Page load can complete before this data has streamed in from the server. | ||
...EventHandlerFragment @defer | ||
} | ||
`, | ||
key, | ||
); | ||
|
||
const onClick = useCallback(async () => { | ||
// Once the user clicks, we may need to wait for the data to finish loading. | ||
const userData = await waitForFragmentData( | ||
graphql` | ||
fragment EventHandlerFragment on User { | ||
age | ||
} | ||
`, | ||
user, | ||
); | ||
|
||
if (userData.age < 10) { | ||
alert("Hello kiddo!"); | ||
} else if (userData.age < 18) { | ||
alert("Hello young person!"); | ||
} else { | ||
alert("Hello adult person!"); | ||
} | ||
}, [user]); | ||
|
||
return ( | ||
<div> | ||
My name is {user.name} | ||
<button onClick={onClick}>Greet</button> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
### Arguments | ||
|
||
* `environment`: `IEnvironment`. A Relay environment. | ||
* `fragment`: GraphQL fragment specified using a `graphql` template literal. | ||
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from. | ||
* The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared. | ||
|
||
### Return Value | ||
|
||
* A `Promise<T>` where `T` is the data defined in the fragment. | ||
|
||
The Promise will wait for all network data to become avaliable as well as any [`@live` Relay Resolver](../../guides/relay-resolvers/live-fields.md) to be in a non-suspended state before it resolves. | ||
|
||
In the case of a network error, or a field-level error due to [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.md) or [`@required(action: THROW)`](../../guides/required-directive.md), the Promise will reject with an error. | ||
|
||
<DocsRating /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters