Refetching Queries with Different Data
When referring to "refetching a query", we mean fetching the query again for different data than was originally rendered by the query. For example, this might be to change a currently selected item, to render a different list of items than the one being shown, or more generally to transition the currently rendered content to show new or different content.
useQueryLoader
/ loadQuery
#
When using Similarly to Refreshing Queries with useQueryLoader
, we can also use the useQueryLoader
Hook described in our Fetching Queries for Render section, but this time passing different query variables:
Let's distill what's going on here:
- We call
loadQuery
in the event handler for refetching, so the network request starts immediately, and then pass thequeryRef
tousePreloadedQuery
, so it renders the updated data. - We are not passing a
fetchPolicy
toloadQuery
, meaning that it will use the default value of'store-or-network'
. We could provide a different policy in order to specify whether to use locally cached data (as we covered in Reusing Cached Data For Render). - Calling
loadQuery
will re-render the component and may causeusePreloadedQuery
to suspend (as explained in Loading States with Suspense). This means that we'll need to make sure that there's aSuspense
boundary wrapping theMainContent
component, in order to show a fallback loading state.
#
If you need to avoid SuspenseIn some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use fetchQuery
instead, and manually keep track of a loading state:
note
In future versions of React when concurrent rendering is supported, React will provide an option to support this case and avoid hiding already rendered content with a Suspense fallback when suspending.
Let's distill what's going on here:
- When refetching, we now keep track of our own
isRefetching
loading state, since we are avoiding supending. We can use this state to render a busy spinner or similar loading UI inside theMainContent
component, without hiding theMainContent
. - In the event handler, we first call
fetchQuery
, which will fetch the query and write the data to the local Relay store. When thefetchQuery
network request completes, we callloadQuery
so that we obtain an updatedqueryRef
that we then pass tousePreloadedQuery
in order render the updated data, similar to the previous example. - At this point, when
loadQuery
is called, the data for the query should already be cached in the local Relay store, so we usefetchPolicy
of'store-only'
to avoid suspending and only read the already cached data.
useLazyLoadQuery
#
When using Similarly to Refreshing Queries with useLazyLoadQuery
, we can also use the useLazyLoadQuery
Hook described in our Lazily Fetching Queries during Render section, but this time passing different query variables:
Let's distill what's going on here:
- We update the component in the event handler for refreshing by setting new query args in state. This will cause the
MainContent
component that usesuseLazyLoadQuery
to re-render with the newvariables
andfetchKey
, and refetch the query upon rendering. - We are passing a new value of
fetchKey
which we increment on every update. Passing a newfetchKey
touseLazyLoadQuery
on every update will ensure that the query is fully re-evaluated and refetched. - We are not passing a new
fetchPolicy
touseLazyLoadQuery
, meaning that it will use the default value of'store-or-network'
. We could provide a different policy in order to specify whether to use locally cached data (as we covered in Reusing Cached Data For Render). - The state update in
refetch
will re-render the component and may cause the component to suspend (as explained in Loading States with Suspense). This means that we'll need to make sure that there's aSuspense
boundary wrapping theMainContent
component, in order to show a fallback loading state.
#
If you need to avoid SuspenseIn some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use fetchQuery
instead, and manually keep track of a loading state:
note
In future versions of React when concurrent rendering is supported, React will provide an option to support this case and avoid hiding already rendered content with a Suspense fallback when suspending.
Let's distill what's going on here:
- When refetching, we now keep track of our own
isRefetching
loading state, since we are avoiding supending. We can use this state to render a busy spinner or similar loading UI inside theMainContent
component, without hiding theMainContent
. - In the event handler, we first call
fetchQuery
, which will fetch the query and write the data to the local Relay store. When thefetchQuery
network request completes, we update our state so that we re-render an updatedfetchKey
andfetchPolicy
that we then pass touseLazyLoadQuery
in order render the updated data, similar to the previous example. - At this point, when we update the state, the data for the query should already be cached in the local Relay store, so we use
fetchPolicy
of'store-only'
to avoid suspending and only read the already cached data.
Is this page useful?