Differences with upcoming Relay Hooks in react-relay
jstejada opened this issue ยท 14 comments
This is an issue to track the differences between the apis exposed in this package and the ones we will expose as part of Relay's react-relay
package. Hopefully, this can help the community decide on whether they're safe to adopt and the cost of migration, as well as inform potential changes to the api.
useQuery
-
useQuery
will no longer takeenvironment
as an argument. Instead it reads the environment set in context; this also implies that it no longer sets any React context.- Since queries with
useQuery
no longer set context, we will expose a newRelayEnvironmentProvider
component that takes anenvironment
and sets it in context; variables will no longer be part of context. ARelayEnvironmentProvider
should be rendered once at the root of the app, and multiple useQuery's can be rendered under this environment provider.
- Since queries with
-
useQuery
will now take afetchPolicy
as part of a 3rd configuration argument, to determine whether it should use data cached in the Relay store and whether to send a network request. The options are:-
store-or-network
(default): Reuse data cached in the store; if the whole query is cached, skip the network request -
store-and-network
: Reuse data cached in the store; always send a network request. -
network-only
: Don't reuse data cached in the store; always send a network request. (This is the default behavior of Relay's existingQueryRenderer
. -
store-only
: Reuse data cached in the store; never send a network request.
-
-
useQuery
returns a single data object with the query's data, and nothing else. -
useQuery
is integrated with Suspense for rendering loading states. This means that depending on thefetchPolicy
, if the query can't render due to missing data (i.e. if the data isn't cached), the query will suspend until the network request completes, and the loading state should be rendered with aSuspense
boundary around the query. -
useQuery
will throw an error if an error occurs, which should be caught by a React Error Boundary around the query.
useFragment
-
useFragment
will no longer take a "fragment spec" (i.e. a map of keys to fragment definitions). Instead, it will always take a single fragment definition as the first argument, and a fragment reference as the second argument. If multiple fragments need to be used in a single component,useFragment
can be used multiple times. -
useFragment
takes a fragment definition and a fragment ref, and returns the data for that fragment. Fragment refs are internal Relay objects that represent pointers to specific instances of the data; e.g. if we have a fragment on theUser
type, the fragment ref specifies which User, for example User with id 4. The fragment ref is not a new concept; it is the same prop that existing RelayModern containers currently take, only that it is explicitly exchanged for the data inside the component via callinguseFragment
, instead of that being hidden in the HOC code. -
useFragment
also subscribes to changes in the data, like the HOC version. -
useFragment
is also integrated with Suspense, meaning that if it has any missing data it will suspend until it's parent query completes. This enables rendering of data that is partially cached in the Relay store, or data that has been @defer'd.
Pagination and Refetch
Pagination and Refetch will have completely separate Hooks APIs (one for pagination, one for refetch), and also integrated with Suspense. They will be quite different from the apis exposed here as configuration to useFragment
, so the migration cost might be higher if the api from this repo is adopted.
Mutations and Susbcriptions
Mutations and Subscriptions will also have completely separate Hooks APIs, and will also integrated with Suspense; the details of what the right APIs with Suspense will be are still under consideration.
Backwards Compatibility
Everything will be released in a backwards compatible way, meaning that new Relay Hooks will work with existing containers. Note that as of Relay v5.0.0 (will be released in the coming days), our existing RelayModern containers will no longer consume variables from context, but instead consume variables via fragment ownership. As mentioned before, Relay context will no longer contain variables; only an environment.
Excellent issue.
This project does not want to be a substitute for react-relay. The initial purpose of the project was to imagine its own relay version with hooks and to propose features to be integrated into the facebook/relay repository.
At the moment there is not a version of the official hooks available otherwise there would be a dependency with the original version and I would have added new features, not modifying the existing ones.
The goal is to help make relay better and easier to use.
Now, thanks to this information, I will be able to make relay-hooks more similar to the one that will be distributed in react-relay so those who want can get familiar with the hooks version.
Thanks @morrys! Oh yeah definitely, wasn't implying that it was. This is great, and we'd also love to hear your feedback when we make the new apis public. Mostly just wanted to document the main differences with the upcoming apis so the community could be aware.
Thanks!!
I knew relay was working on a hooks api and the reason why I'm using this project is to make migration less painful when the relay is shipped with official hooks support. It's good to see morrys is trying to mimic the coming official api as closely as possible and this info is certainly helpful for his efforts.
Regarding the integration of Suspense, we've been experimenting ways of using Relay through hooks at my company for about 6 months now, and the API we ended up with has been open-sourced at https://github.com/levels3d/offblast
TL;DR we found that suspending in the useQuery
hook is usually an anti-pattern with GraphQL as we tends to query all the data needed by the many components of a page in a single query (and so a single useQuery
call) near the root of the React tree of the page. Suspending in this place means showing a single loading indicator / fallback content for almost the entire viewport, something we found undesirable as we would rather render most of the layout of the page and only show placeholders in the components that actually use the fetched data.
Additionally, we found it useful to add an additional "skip" behavior to the fetchPolicy
argument for cases were we want to skip the query entirely (since you can't put a hook in a condition).
@sibelius Not yet, though I don't think it would take me much time to publish a fork
open sourced here facebook/relay@b83aace
@morrys @sibelius @renanmav Is there any plan to support subscriptions via hooks?
EDIT: I would be more than happy to contribute the useSubscription
that follows the upstream version. (https://github.com/facebook/relay/blob/e2d5e5c4630931f35495d105353594b42babc818/packages/relay-experimental/useSubscription.js)
@stramel, @rbalicki2 added support for useSubscription
internally and it will be included in the next react-relay@experimental
release
@jstejada, @rbalicki2 In the PR #90 there is a different implementation and use of usePreloadedQuery.
Being in Relay still in the experimental phase I would like your opinion about it.
Is the intention to deprecate this library once Relay's hooks implementation is no longer "experimental"?
My biggest concern is that Relay's implementation relies on Suspense, which currently doesn't support SSR.
It all depends on how relay-experimental it will be and surely the repository will be supported as long as it is used.
Is the idea with the experimental official useQuery
that it it will suspend for loading and throw an error (to be caught by an error boundary for the error state, rather than the {error, props}
(and loading == !props
) API?
This seems like the hardest thing to migrate because it significantly changes the component composition pattern you need to use.
useQuery returns a single data object with the query's data, and nothing else.
// relay-hooks
const {props, error, retry, cached} = useQuery(query, variables, options);
// relay
const data = useQuery(query, variables, options);
Just as an FYI for anyone following this issue, we've released Relay Hooks in v11 of Relay! https://github.com/facebook/relay/releases/tag/v11.0.0