redux RTK查询|使来自另一个API服务的API服务的缓存无效

cidc1ykv  于 2023-02-16  发布在  其他
关注(0)|答案(2)|浏览(149)

我已经创建了多个RTK查询API服务,并将其拆分为多个文件。对于此问题,我有两个服务:"Contracts"和"Properties"。合同服务应该能够在合同更新时使Properties高速缓存无效,但是即使在向合同服务提供"Properties"标签之后,高速缓存也不会无效。
下面是我的设置:
属性:

export const propertyApi = createApi({
    reducerPath: 'propertyApi',
    baseQuery: fetchBaseQuery({ baseUrl: `${API_BASE_URL}/properties` }),
    tagTypes: ['Properties'],
    endpoints: builder => ({
        // many endpoints
    })
})

export const {
    // many hooks
} = propertyApi

合同:

export const contractApi = createApi({
    reducerPath: 'contractApi',
    baseQuery: fetchBaseQuery({ baseUrl: `${API_BASE_URL}/contracts` }),
    tagTypes: ['Contracts', 'Properties'],
    endpoints: builder => ({
        // ...
        modifyContract: builder.mutation<Contract, { contract: Partial<ContractDto>, contractId: Contract['id'], propertyId: Property['id'] }>({
            query: ({ contract, contractId }) => {
                return {
                    url: `/${contractId}`,
                    method: 'PATCH',
                    credentials: "include",
                    body: contract
                }
            },
            // to my understanding, this should invalidate the property cache for the property with 'propertyId', but it doesn't seem to work
            invalidatesTags: (_res, _err, { propertyId }) => ['Properties', 'Contracts', { type: 'Properties', id: propertyId }]
        })
    })
})

export const {
    // ...
    useModifyContractMutation
} = contractApi

商店设置:

export const STORE_RESET_ACTION_TYPE = 'RESET_STORE'

const combinedReducer = combineReducers({
    [photoApi.reducerPath]: photoApi.reducer,
    [authApi.reducerPath]: authApi.reducer,
    [propertyApi.reducerPath]: propertyApi.reducer,
    [cronApi.reducerPath]: cronApi.reducer,
    [contractApi.reducerPath]: contractApi.reducer,
    auth: authReducer
})

const rootReducer: Reducer = (state: RootState, action: AnyAction) => {
    if (action.type === STORE_RESET_ACTION_TYPE) {
        state = {} as RootState
    }
    return combinedReducer(state, action)
}

export const store = configureStore({
    reducer: rootReducer,
    middleware: (getDefaultMiddleware) => {
        return getDefaultMiddleware().concat([
            photoApi.middleware,
            authApi.middleware,
            propertyApi.middleware,
            cronApi.middleware,
            contractApi.middleware,
            errorHandlerMiddleware
        ])
    }
})

setupListeners(store.dispatch)

export type AppDispatch = typeof store.dispatch
export type RootState = ReturnType<typeof store.getState>
export type AppThunk<ReturnType = void> = ThunkAction<
    ReturnType,
    RootState,
    unknown,
    Action<string>
>

export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
zpjtge22

zpjtge221#

如果您像我一样,对API的制作没有发言权,但仍然必须使其他API的Tag无效,这里有一个变通方案:

...
  query: ...
  onCacheEntryAdded: (args, { dispatch }) => {
    dispatch(otherAPI.util.invalidateTags(["Tag"]))
  }

缺点:它在查询解决之前触发,因此我们无法检查是否成功

oyxsuwqo

oyxsuwqo2#

如果那些API服务有相互依赖的数据(这暗示了它们应该相互失效)它们不应该是多个api服务它们实际上只是一个api的多个端点,我们在文档的多个地方都这样声明。
the quickstart tutorial为例:
通常,应用程序需要与之通信的每个基URL应该只有一个API切片。例如,如果站点同时从/api/posts和/api/users提取数据,则将有一个以/api/作为基URL的API切片,并为posts和users分别定义端点。这样,您就可以通过定义端点之间的标记关系来有效利用自动重新提取。
相反,如果你想把一个API拆分成多个文件,你可以使用文档中描述的code splitting机制。
这也意味着您不必在configureStore调用中添加很多API切片和中间件,而只需添加一个。

相关问题