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 Data#
Some 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 refetchable#
You 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, 
@refetchableand@argumentDefinitions.@refetchabletells 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@refetchableaqueryNameprop 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$includeFullBiothat's required and a boolean. However, if the one who spreads this fragment does not pass that variable, it should default to false".$includeFullBiois 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@argumentDefinitionshere.- In our selection, we use 
$includeFullBiovia the built-in GraphQL directive@includeto control whether thebiofield should be included in the query or not. Read more about GraphQL directives and the built in directives@includeand@skiphere. - Whenever a fragment has a 
@refetchabledirective on it with aqueryName, RescriptRelay will autogenerate auseRefetchableReact hook that you can use, in addition to the defaultusehook.useRefetchableworks 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 
bioobject in the data. If it's not there, we render a button to refetch the fragment with$includeFullBioset totrue. Otherwise, we render a simple UI for showing the full bio. - Note the use of the function 
UserFragment.makeRefetchVariablesto 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.makeRefetchVariablesis also autogenerated by RescriptRelay whenever there's a@refetchabledirective 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 
@refetchablewill give you auseRefetchablehook, which in turn gives you arefetchfunction that you can use to refetch the fragment. - When refetching, you provide only the parts of 
variablesthat 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 up#
That'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 Reference#
Adding @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.