redux-toolkit icon indicating copy to clipboard operation
redux-toolkit copied to clipboard

Feature Request: queries with matching tags should avoid refetching

Open amirghafouri opened this issue 1 year ago • 2 comments

Imagine the following pattern:

I have hooks such as useFetchTrendingPostsQuery, useFetchFeaturedPostsQuery, useFetchTechnologyPostsQuery, etc... which all return different entities of the same type.

I have a Post component, which I want to accept only a postId prop.

There is a useFetchPostQuery which would accept a postId param and fetch a single post.

However, I don't want to trigger this query if the post has already been fetched by one of: useFetchTrendingPostsQuery, useFetchFeaturedPostsQuery, useFetchTechnologyPostsQuery.


I can't really use selectFromResult, because Post is a generic component and it would have to check all of the different api queries for different types of posts.

I think I could use extraReducers to put the results from the various query hooks for different types of posts into a single store slice called posts and check that, but that feels like it defats the point of having rtk-query?


One thing I could do is provide tags from the results of those queries, such as:

fetchFeaturedPosts: builder.query({
      providesTags: data => {
          return data.map(i => ({ type: 'post', id: i.id }));
      },
      query: fetchFeaturedPostsQuery
}),
fetchTrendingPosts: builder.query({
      providesTags: data => {
          return data.map(i => ({ type: 'post', id: i.id }));
      },
      query: fetchTrendingPostsQuery
}),
fetchPost: builder.query({
      providesTags: (data, error, arg) => {
          return [{ type: 'post', id: arg.postId }];
      },
      query: fetchPost
}),

I would just need a way to link the {type: 'post', id: postId } tag back to useFetchPost in a way that would make it avoid fetching that specific post if the postId matched.

Essentially, RTK-Query is a document cache by default, but via tags I think user's could have a handy way to manually create normalized relationships between the different queries by processing the data results in providesTags.

amirghafouri avatar Feb 14 '24 19:02 amirghafouri

Tags are really not meant for normalization - they are really only for refetching or removing unused cache items.

In your example, if something would be prevented from invalidating, you'd end up with outdated in the cache that might surface at some unfortunate point of time in the future.

Keep in mind that a query will only refetch on invalidation if your app is actually using it at that point in time. If your app is not using it any more at the time of invalidation, it will not refetch. It will just be removed from cache.

phryneas avatar Feb 14 '24 21:02 phryneas

@phryneas I appreciate you taking the time to respond.

It's not that we want to prevent invalidation, it's that we want to establish a uni-directional relationship for mirroring another query's cache. Whatever logic applies to invalidating the other cache would apply to this one as well.

I understand this wasn't the original intention of tags, but a similar api would be useful I think.

If there is a valid subscription for a piece of information I've manually tagged as { type: 'post', id: 'abc' }, I think I should be able to manually tell the library that this other query doesn't need to refetch when it gets called with 'abc'. I am telling it that I know these queries are returning identical entities.

amirghafouri avatar Feb 14 '24 22:02 amirghafouri