-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start Relay Resolver Docs with basic examples #480
Closed
youngkidwarrior
wants to merge
1
commit into
zth:master
from
youngkidwarrior:ykw/relay-resolver-docs
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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,170 @@ | ||
--- | ||
id: relay-resolvers | ||
title: Relay Resolvers | ||
sidebar_label: Relay Resolvers | ||
--- | ||
|
||
#### Recommended background reading | ||
- [Relay Resolvers](https://relay.dev/docs/guides/relay-resolvers/) | ||
|
||
|
||
## Enabling Experimental Resolvers | ||
Relay Resolvers are still considered experimental. To use them you must ensure that the `ENABLE_RELAY_RESOLVERS`` runtime feature flag is enabled, and that the `enable_relay_resolver_transform`` feature flag is enabled in your project’s Relay config file. | ||
|
||
```js | ||
// relay.config.js | ||
module.exports = { | ||
//... | ||
featureFlags: { | ||
enable_relay_resolver_transform: true, | ||
}, | ||
|
||
//... | ||
}; | ||
``` | ||
|
||
```js | ||
//SomeComponent.res | ||
RescriptRelay.relayFeatureFlags.enableRelayResolvers = true | ||
|
||
@react.component | ||
let make = () => { | ||
// | ||
} | ||
``` | ||
|
||
|
||
## Basic Example | ||
```js | ||
// UserGreetingResolver | ||
/** | ||
* @RelayResolver | ||
* | ||
* @onType User | ||
* @fieldName greeting | ||
* @rootFragment GreetingResolver | ||
* | ||
* A User Greeting | ||
*/ | ||
type t = string | ||
|
||
module Fragment = %relay(` | ||
fragment UserGreetingResolver on User { | ||
firstName | ||
lastName | ||
} | ||
`) | ||
|
||
let default = Fragment.makeRelayResolver(({firstName, lastName}) => Some(`Hello ${firstName} ${lastNamee}!`)) | ||
|
||
``` | ||
|
||
|
||
|
||
|
||
## Using Relay Resolvers | ||
Relay Resolvers utilize special conventions in order to add a new field onto a type. | ||
|
||
Rescript Relay Resolvers actively lean on Rescript's type inference to simplify the resolver boilerplate. Still, a resolver type must be explicitly defined with `type t`. | ||
|
||
### FileName | ||
Resolver files must end with the word `Resolver` for the relay compiler to compile them | ||
|
||
- ❌ ~~ResolveUserGreeting.res~~ | ||
- ❌ ~~GenerateUserGreetingField.res~~ | ||
- ✅ UserGreetingResolver.res | ||
|
||
### Docblock | ||
The Relay compiler looks for the following fields in any docblocks that includes @RelayResolver: | ||
|
||
- **@RelayResolver (required)** | ||
- **@rootFragment (optional)** The name of the fragment read by readFragment | ||
- **@deprecated (optional)** Indicates that the field is deprecated. May be optionally followed text giving the reason that the field is deprecated. | ||
|
||
The docblock may also contain free text. This free text will be used as the field’s human-readable description, which will be surfaced in Relay’s editor support on hover and in autocomplete results. | ||
``` | ||
/** | ||
* @RelayResolver | ||
* | ||
* @onType User | ||
* @fieldName greeting | ||
* @rootFragment UserGreetingResolver *Note* this matches our filename | ||
* | ||
* The status of a todo | ||
*/ | ||
``` | ||
|
||
### Relay Resolver Conventions | ||
In order for Relay to be able to call a Relay Resolver, it must conform to a set of conventions: | ||
|
||
- The resolver must have a type `t` defined. | ||
- The resolver must read its fragment using the special `makeRelayResolver` function. | ||
- The resolver function must be pure. | ||
- The resolver’s return value must be immutable. | ||
- The resolver return type must be of `option<t>` | ||
|
||
Unlike server resolvers, Relay Resolvers may return any Rescript value, however it must be wrapped in `Option`. This includes functions, arrays, tuples, variants, etc. However, we generally encourage having Relay Resolvers return scalar values and only returning more complex JavaScript values (like functions) as an escape hatch. | ||
|
||
## Passing arguments to resolver fields | ||
For resolvers, we support two ways of defining field arguments: | ||
|
||
- **GraphQL:** Arguments that are defined via `@argumentDefinitions`` on the resolver's fragment. | ||
- **JS Runtime:** Arguments that can be passed directly to the resolver function. | ||
You can also combine these, and define arguments on the fragment and on the resolver's field itself, Relay will validate the naming (these arguments have to have different names), and pass GraphQL arguments to fragment, and JS arguments to the resolver's function. | ||
|
||
### Defining Resolver field with Fragment Arguments | ||
```js | ||
// UserGreetingResolver.res | ||
/** | ||
* @RelayResolver | ||
* @rootFragment UserGreetingResolver | ||
*/ | ||
|
||
module Fragment = %relay(` | ||
fragment UserGreetingResolver on User | ||
@argumentDefinitions(someArg: {type: "String"}) { | ||
greeting(someArg: $someArg){ | ||
__typename | ||
} | ||
} | ||
`) | ||
|
||
let default = Fragment.makeRelayResolver(({greeting}) => Some(greeting.__typemame)) | ||
``` | ||
|
||
### Using Resolver field with arguments for Fragment | ||
```js | ||
|
||
module Query = %relay( | ||
`Query MyQuery($id: ID, $greetingText: String) { | ||
node(id:$id) | ||
... on User { | ||
greeting(custonText: $greetingText) | ||
} | ||
} | ||
` | ||
) | ||
|
||
@react.component | ||
let make = () => { | ||
let data = Query.use(~variables={ | ||
id: "abc123", | ||
someArg:"Waasssaaaap?" | ||
}) | ||
|
||
switch queryData.node { | ||
| Some(user) => <div> {React.string(user.greeting)} </div> | ||
| None => React.null | ||
} | ||
} | ||
``` | ||
|
||
### Defining Resolver field with Runtime (JS) Arguments | ||
Relay resolvers also support runtime arguments that are not visible/passed to fragments, but are passed to the resolver function itself. | ||
|
||
You can define these fragments using GraphQL’s Schema Definition Language in the @fieldName | ||
|
||
``` | ||
//TODO | ||
|
||
``` |
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a more compact notation now that we could perhaps also show. Can't find a link to it now though.