-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Hey team!
I've been diagnosing some performance issues in an application and I came across a somewhat unexpected culprit. We're using RTK Query for API data fetching & caching, as well as some global UI state management that is not related to API data.
I found that the auto-generated useQuery
hooks add some additional overhead that seems related to subscription tracking. On the page in question, there were only 10-12 endpoints being used but some of the endpoints had 1000-4000 subscriptions (found by logging out the endpoint name + query args + keys in the state.api.subscriptions
object)
We load most of this data when the page is rendered and don't often refetch it from sub-components. As an experiment, I swapped some of the generated useGetXQuery
hook calls with the useQueryState
hook that is not auto-generated, i.e. api.endpoints.getUser.useQueryState
, and found that the performance of mounting/unmounting components that called these hooks was much faster.
I wanted to raise the issue to see if there's any obvious reason for this extra overhead. All of the documentation seems to point to just using the generated query hooks and not reaching for the useQueryState
/ useQuerySubscription
hooks available on each endpoint definition.
I've put together a minimal reproduction repo to showcase this issue. The UseQueryChild
and UseQueryStateChild
components are intentionally calling the respective hook multiple times for the sake of simulating how many consuming components our real application might have at one time. You'll notice that the conditional render of the UseQueryStateChild
component is much faster than the UseQueryChild
.
From my testing, it seems like useQueryState
will still notify consuming components if the underlying data changes (i.e. something triggers an update to the cache), so is there any benefit to using useQuery
over useQueryState
if we prefetch the data at the top of the page tree and know that it will be cached by the time the consuming components use it (i.e. no additional API request needs to be fired)?
Reproduction repo: https://github.com/brandongregoryscott/rtk-query-subscription-performance
Reproduction demo: