Refetching and Loading More Data
#
Recommended background reading- Queries and mutations in GraphQL
- A Guided Tour of Relay: Re-Rendering Fragments with Different Data
- React documentation: Suspense for Data Fetching
#
Refetching and Loading More DataSome of the following features comes with some constraints if your GraphQL server schema does not follow the Relay specification. Read more about using RescriptRelay with schemas that don't conform to the Relay specification here.
Sometimes you'll want to refresh or refetch data in specific parts of your views without re-issuing the full query the data was originally rendered from. Relay makes this very simple if your schema conforms to the Relay specification and implements the Node
interface, or if your fragment is on the Query
or Viewer
type. This page will focus on Relays feature to refetch a fragment.
#
Making a fragment refetchableYou can make a fragment refetchable by adding the @refetchable(queryName: "")
directive to it. Let's look at an example of making a fragment refetchable and refetching it with. Here's a component showing some information about a user, and then rendering a "Show bio"-button to refetch the fragment it uses, but include more information about the user:
Whew, new stuff to break down. Let's start from the top:
- We've added two directives to our fragment,
@refetchable
and@argumentDefinitions
.@refetchable
tells Relay that this fragment can be refetched, and also tells the Relay compiler to automatically generate a query to use when refetching the fragment. Remember, fragments always have to end up in a query to be usable, so you need a query to refetch a fragment. But, Relay can autogenerate the query for your, so the only thing you need to think about is giving@refetchable
aqueryName
prop with a name for your refetch query. @argumentDefinitions
, is a way to define that a fragment can take arguments, much like props in React. This is a very neat feature and you're encouraged to use it as much as you can when it makes sense. Basically, we're saying that "this fragment needs a variable$includeFullBio
that's required and a boolean. However, if the one who spreads this fragment does not pass that variable, it should default to false".$includeFullBio
is how we'll control if we should fetch the extra data or not, and since we don't want to load the extra data before the user explicitly asks for it, we'll make sure it defaults tofalse
. You're encouraged to read more about@argumentDefinitions
here.- In our selection, we use
$includeFullBio
via the built-in GraphQL directive@include
to control whether thebio
field should be included in the query or not. Read more about GraphQL directives and the built in directives@include
and@skip
here. - Whenever a fragment has a
@refetchable
directive on it with aqueryName
, RescriptRelay will autogenerate auseRefetchable
React hook that you can use, in addition to the defaultuse
hook.useRefetchable
works just likeuse
, only that it returns a tuple containing both the data and a function to refetch the fragment instead of just the data. - When rendering, we check for the
bio
object in the data. If it's not there, we render a button to refetch the fragment with$includeFullBio
set totrue
. Otherwise, we render a simple UI for showing the full bio. - Note the use of the function
UserFragment.makeRefetchVariables
to make the refetch variables. The reason we're not passing raw variables just like we'd normally do is that when making a refetch, all variables are optional. Relay lets you supply only the variables you want to change from the last fetch of the fragment, and it will re-use anything you don't pass to it from the last fetch. So, if you simply doUserFragment.makeRefetchVariables()
without passing any changed variables, the fragment will be refetched with the same configuration it was fetched before.makeRefetchVariables
is also autogenerated by RescriptRelay whenever there's a@refetchable
directive on the fragment, and its a helper to let you easily provide only the parts of the variables that has changed.
Let's sum up:
- Defining a fragment as
@refetchable
will give you auseRefetchable
hook, which in turn gives you arefetch
function that you can use to refetch the fragment. - When refetching, you provide only the parts of
variables
that you want to change. This means that providing an emptyFragment.makeRefetchVariables()
will refetch the fragment with the same configuration as it was last fetched with. - Control what's fetched at what point with GraphQL variables and
@argumentDefinitions
, as examplified above.
#
Wrapping upThat's how you refetch a fragment. This can be used to implement a number of patterns like polling, "Read more"-functionality, deferring loading certain expensive data until needed, and so on. A tool worthy of your toolbox!
#
API ReferenceAdding @refetchable
to a fragment will make RescriptRelay add a useRefetchable
hook to your fragment. That useRefetchable
hook takes the same parameter as the regular use
hook on a fragment, an object containing a fragment reference for this particular fragment.
It returns (fragmentData, refetchFunction)
, where fragmentData
is the data for the fragment.
refetchFunction
#
The refetch function that useRefetchable
returns take the same arguments as the use
hook on a query with one important difference: the properties of the variables
object will all be optional. This is because you only need to provide what properties in the variables you want to change from the last fetch when refetching. RescriptRelay autogenerates a makeRefetchVariables
for you function that simplifies this.
makeRefetchVariables
#
makeRefetchVariables
is autogenerated and available on your fragment when you've defined your fragment as @refetchable
. It's a helper function to make it easy to build your refetch variables by only providing what you want to change.