relay icon indicating copy to clipboard operation
relay copied to clipboard

Async Relay Resolvers

Open alex-statsig opened this issue 2 years ago • 7 comments

There is no mention on Relay Resolvers about async resolvers / promises, and they seem to not work currently (I get an error about the object not having an "id" field, since the unresolved promise does not have the field; related #4536). I'm trying to use the experimental Relay Resolvers to nicely manage optimistic states / updaters and querying for several external REST APIs for a client-only app. To do this, async resolvers are necessary to make the REST calls. The Relay Resolvers system seems like a really cool way to support something like this, since I can just write clientside code to fetch data for a field and have relay manage syncing that across my app / fetching as needed if its not cached etc. The lack of async seems like a restrictive limitation atm. Is this something that is planned to be changed?

alex-statsig avatar Nov 24 '23 02:11 alex-statsig

We are planing to land public documentation of resolvers in Dec/Jan but in the mean time, Live Resolvers can return a suspense sentinel to indicate that they are in a loading state. You can get the sentinel value from here: https://github.com/facebook/relay/blob/e854fa04acfef0421001d507b220a0c74f7f38b6/packages/relay-runtime/store/experimental-live-resolvers/LiveResolverSuspenseSentinel.js#L18

This should cause any component reading that field to suspend.

captbaritone avatar Nov 27 '23 18:11 captbaritone

We are planing to land public documentation of resolvers in Dec/Jan but in the mean time, Live Resolvers can return a suspense sentinel to indicate that they are in a loading state. You can get the sentinel value from here:

https://github.com/facebook/relay/blob/e854fa04acfef0421001d507b220a0c74f7f38b6/packages/relay-runtime/store/experimental-live-resolvers/LiveResolverSuspenseSentinel.js#L18

This should cause any component reading that field to suspend.

Gotcha, then I assume I would manually commit an update to the store once my promise resolves. Although I'm not sure how to get a reference to the store from there?

ex. something like this:

function myResolver() {
  fetchData()
    .then((result) => {
      store.commitLocalUpdate(..., result);
    })
    .catch((e) => store.commitLocalUpdate(..., null));
  return suspenseSentinel();
}

Thanks for the info about documentation timeline / "suspense sentinels", I was just eager to try this out on a personal project early!

alex-statsig avatar Nov 27 '23 21:11 alex-statsig

Hello folks! Wondering when suspenseSentinel (and also LiveState type) will be available via Relay and @types/relay-runtime. We are very interested in using these features here at Atlassian.

Some documentation would be amazing too! 🙏🏾

Thanks so much!!!

ameyms avatar Aug 06 '24 06:08 ameyms

Documentation can be found here:

  • https://relay.dev/docs/guides/relay-resolvers/live-fields/
  • https://relay.dev/docs/guides/relay-resolvers/suspense/

I'll try to raise a PR for the types later today :)

EDIT: Here's the PR https://github.com/DefinitelyTyped/DefinitelyTyped/pull/70229

tobias-tengler avatar Aug 06 '24 06:08 tobias-tengler

@types/relay-runtime 17.0.4 now includes the types for LiveState<T> and suspenseSentinel.

tobias-tengler avatar Aug 06 '24 15:08 tobias-tengler

Thank you so much for the quick PR @tobias-tengler!!!! You literally unblocked me!!

ameyms avatar Aug 07 '24 05:08 ameyms

@captbaritone (sorry for the @ mention)

But... would it be possible to throw in a quick example/psuedocode here of how suspenseSentinel is to be used in conjunction with Promises (due to a server API call via fetch)

ameyms avatar Aug 07 '24 06:08 ameyms