Skip to content
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

[Rough Draft] Document Relay Resolvers #4547

Closed
wants to merge 6 commits into from

Conversation

captbaritone
Copy link
Contributor

@captbaritone captbaritone commented Dec 10, 2023

For the last few years we've been experimenting with expanding Relay Resolvers to allow them to return client state that can change over time. We are now close to releasing this new capability as a stable part of Relay, and so these docs my initial stab at documenting their full feature set. I expect these docs will go through a few revisions before we land, so they still have a few "TODO"s scattered around in the docs (and in this PR).

Warning

These docs document the API we expect to ship. Today it still requires enabling both compiler and runtime feature flags, and using a special instance of the Relay Store. Additionally, some of the types and values what will be exported as top level exports of the relay-runtime module are not yet exported. Following these docs today is not expected to work Thanks for your patience!

TODO

List of work items still to be done for these docs:

  • Ensure we expose the LiveState type from relay-runtime root
  • Decide on canonical name for Live Resolvers ("live data?", "live resolvers?", "live fields?")
    • How does this align with "derived fields"
  • Unify around name for "client schema". Client resolver schema? Client state schema?
    • This is confusing because we already have client schema extensions
  • What about type exports for TypeScript?
    • LiveState
    • SuspenseSentinel
  • Expose our live resolver batching method directly on Relay environment
  • I think that we currently allow Resolver types to be @deprecated, but in documenting this, I realized that we the spec does not actually allow this.

@@ -70,7 +70,7 @@ Flow users will now get types inferred from `graphql` literals with more Relay A

### Relay Resolver improvements

A significant portion of our development effort since our last release has gone into improving [Relay Resolvers](https://relay.dev/docs/guides/relay-resolvers) (a mechanism for exposing derived data in the graph). It is worth noting that Relay Resolvers are still experimental and API changes might occur in the future.
A significant portion of our development effort since our last release has gone into improving [Relay Resolvers](https://relay.dev/api-reference/relay-resolvers/introduction/) (a mechanism for exposing derived data in the graph). It is worth noting that Relay Resolvers are still experimental and API changes might occur in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the last sentence still applicable after we release them as stable? Maybe we can remove the "Relay Resolvers are still experimental" bit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's okay for a blog post to be a point in time artifact. That said, maybe I can add and an "update" section.


## Syntax

When defining a field string after `@RelayResolver` is a GraphQL `TypeName` followed by a dot followed by the field
Copy link
Contributor

@monicatang monicatang Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - Suggestion for clarity (IMO)

Suggested change
When defining a field string after `@RelayResolver` is a GraphQL `TypeName` followed by a dot followed by the field
Relay resolvers are marked via docblocks above a resolver function.
`@RelayResolver` is the tag to indicate the start of any relay resolver definition.
To define a field on a GraphQL model type `TypeName`, add `TypeName` followed by a dot followed by the field

@facebook-github-bot
Copy link
Contributor

@captbaritone has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

export function counter(): LiveState<number> {
return {
read: () => store.getState().counter,
subscribe: (cb) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more descriptive name (like "callback") or a typehint would do wonders here. cb is a bit opaque.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Thanks for pointing that out. Will fix.

* @RelayResolver ProfilePicture
* @weak
*/
export type ProfilePicture = { url: string, height: number, width: numbe };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small typo here should be width: number


### Defining a “strong” type

Strong types ar defined by a docblock followed by an exported function whose name matches the type's name, and which accepts an ID as its first argument and returns an instance of the type’s model [TODO link]. Resolvers that define edges to this type will simply need to return the ID of the object, rather than deriving the model themselves.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it right that the model resolver can only accept one argument (the id argument)? Seems to be the case when I tried it. IIUC, instead of "first" argument we can say "only"?

```

:::note
Relay will takes care of efficiently recomputing resolvers when any of their inputs (in this case the model instance) change, so you don’t need to worry about memoizing your resolver function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Relay will takes care of efficiently recomputing resolvers when any of their inputs (in this case the model instance) change, so you don’t need to worry about memoizing your resolver function.
Relay will take care of efficiently recomputing resolvers when any of their inputs (in this case the model instance) change, so you don’t need to worry about memoizing your resolver function.

}
```

See the [Weak Types](../../guides/relay-resolvers/defining-types.md#Defining a “weak” type) guide for more information including how to define an edge to a weak type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link is somehow broken

@facebook-github-bot
Copy link
Contributor

@captbaritone merged this pull request in 51a82f6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants