RTK Query invalidatesTags 似乎并没有每次都删除缓存数据

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

我有一个 RTK 查询突变端点 rejectApplication,它使 getApplication 查询无效。这些都在同一个 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 }],
}),

问题是我有两个使用 useRejectApplicationMutation 挂钩的组件,但出于某种原因,它们似乎只有一个在查询结果失效后从缓存中正确删除。我可以通过 Redux devtools 观察到这一点,在那里我可以看到 removeQueryResult 操作在一个组件中完成 reject 突变后被调度,但没有在另一个组件中触发。这导致组件中的 getApplication 数据没有改变,从而中断了应用程序的流程。

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

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

所以在这种情况下,没有调用数据的 useEffect 因为数据似乎没有被重新获取,尽管它应该在 reject mutation 完成后失效。奇怪的是,在控制台中它看起来确实应该正确地重新获取无效的应用程序和状态,因为在删除请求后命中了 MSW 端点。

[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)

对我来说,问题似乎是缓存由于某种原因没有正确清除,所以尽管标签无效并且重新获取数据没有正确重置。对可能导致这种不一致的原因有什么想法吗?

invalidatesTags 并不总是从缓存中删除内容。它只会从缓存中删除组件中当前未使用的缓存条目的内容 - 对于其他所有内容,它都会触发重新获取,因此会再次触发请求,如果响应中有新数据,则会更新响应因此。

因此在您的组件中,isFetching 将切换到 true,但数据不会消失 - 在大多数情况下,这是首选行为,因为您不希望所有内容都跳转到加载指示器,但仅在突变后更新显示的数据。

现在,如果您的端点 returns 数据在结构上与它之前返回的数据相同,它也不会是新的 data 对象,而只是旧对象。在重新获取时,RTK-Query 会比较新旧结果,并尽可能保持其引用相等,因此当基础数据实际上根本没有改变时 useEffects 不会被触发。

你的 applicationId 是只代表一个 id 还是代表一个有属性的对象?因为 if 代表一个对象,你应该从

重构你的代码
invalidatesTags: (_result, _error, applicationId) => [
  "Status",
  { type: "Application", id: "LIST" },
  { type: "Application", id: applicationId },
],

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

注意到 applicationId 周围的花括号了吗?这样你就可以从 http 请求的结果中解构你的对象,并将它传递给 id 属性 以使其无效。