RTK Query invalidatesTags doesn't seem to remove cached data every time
Asked Answered
R

2

6

I have an RTK Query mutation endpoint rejectApplication, that invalidates the getApplication query. These are in the same API.

rejectApplication: builder.mutation<RejectResponse, string>({
  query: (applicationId) => ({
    url: `/applications/${applicationId}`,
    method: "DELETE",
  }),
  invalidatesTags: (_result, _error, applicationId) => [
    "Status",
    { type: "Application", id: "LIST" },
    { type: "Application", id: applicationId },
  ],
}),
getApplication: builder.query<ApplicationResponse, string>({
  query: (applicationId: string) => ({
    method: "GET",
    url: `/applications/${applicationId}`,
  }),
  providesTags: (_result, _error, id) => [{ type: "Application", id: id }],
}),

Problem is that I have two components that use the useRejectApplicationMutation hook, but for some reason only one of them seems to correctly remove the query result from cache after it has been invalidated. I can observe this through the Redux devtools, where I can see the removeQueryResult actions being dispatched after the reject mutation has fulfilled in one component, but not firing in the other component. This leads to the getApplication data in the component not changing, which breaks the flow of the application.

const {
  data,
  isLoading: getApplicationIsLoading,
  isError: getApplicationIsError,
} = useGetApplicationQuery(props.application.applicationId as string);

useEffect(() => {
  if (data) {
    dispatch(setIncompleteApplication(data));
  }
}, [data]);

So in this case, the useEffect with data is not called because data doesn't seem to be refetched, although it should be invalidated after reject mutation is fulfilled. Weirdly, in the console it does look like it should be correctly refetching the application and status which are invalidated, as the MSW endpoints are hit after the delete request.

[MSW] 12:37:38 DELETE /v1/applications/XA1234567 (200 OK)
[MSW] 12:37:38 GET /v1/status (200 OK) 
[MSW] 12:37:39 GET /v1/applications/XA1234567 (200 OK)

To me, the problem seems to be that the cache isn't properly cleared for some reason, so although the tags are invalidated and refetches made the data isn't properly reset. Any ideas to what might be causing this inconsistancy?

Raccoon answered 8/12, 2021 at 11:36 Comment(0)
D
3

invalidatesTags does not always remove things from cache. It only removes things from cache for cache entries that are not being used in a component at the moment - for everything else it triggers a refetch, so the request is fired off again and if there is new data in the response, the response is updated accordingly.

So in your component, isFetching will switch to true, but the data will not disappear - in most cases that is the preferred behaviour, as you don't want everything to jump to a loading indicator, but just update displayed data after a mutation.

Now, if your endpoint returns data that is structurally equal to the data it returned before, it will also not be a new data object, but just the old one. On a refetch, RTK-Query compares the old and new result and tries to keep as much of it referentially equal as possible, so useEffects are not fired off when the underlying data did actually not change at all.

Drawtube answered 8/12, 2021 at 13:14 Comment(1)
I see, makes sense. Thanks for the swift reply.Raccoon
P
1

Is your applicationId representing only an id or it represent an object with properties in it? Because if represents an object you should refactor your code from

invalidatesTags: (_result, _error, applicationId) => [
  "Status",
  { type: "Application", id: "LIST" },
  { type: "Application", id: applicationId },
],

to

invalidatesTags: (_result, _error, { applicationId }) => [
  "Status",
  { type: "Application", id: "LIST" },
  { type: "Application", id: applicationId },
],

Notice the curly braces around applicationId? This way you are destructuring your object from the result of the http request and you're passing it to the id property for invalidating.

Provender answered 21/1, 2022 at 13:40 Comment(3)
From the docs, or even the code such that I've found, I'm not clear on what that third argument actually is. I'm console logging to find out - did you have somewhere in the docs where you learned more about the arguments to invalidatesTags?Lancelle
From my console logs, it appears to be the initial argument passed to the query.Lancelle
Hi Caleb, how and where do you console.log to determine the arguments to invalidatesTags? Thanks in advance.Encompass

© 2022 - 2024 — McMap. All rights reserved.