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

rtk-query: Modify refetchOnMountOrArgChange with enhanceEndpoints

Open ericecook opened this issue 2 years ago • 9 comments

I'm using codegen to generate the api spec and would like to specify a refetchOnMountOrArgChange for the whole endpoint - rather than in every component.

Ideally I'd like to do something like

import { injectedApi } from './generated/api'

const enhancedRtkApi = injectedApi.enhanceEndpoints({
    getData: {
      refetchOnMountOrArgChange: 600,
      keepUnusedDataFor: 14400,
    },
  },
})
export { enhancedRtkApi as api }

But it looks like refetchOnMountOrArgChange is part of the query key. I may be missing something, but I couldn't figure out a way to pass query key w/o overriding the generated one

ericecook avatar May 17 '22 19:05 ericecook

I'm not really sure what you mean with "part of the query key". Could you elaborate?

phryneas avatar May 17 '22 20:05 phryneas

I'm still picking up rtk-query, so maybe I'm misunderstanding how it fits together - but I think a configuration like this is valid:

const injectedRtkApi = api.injectEndpoints({
  endpoints: (build) => ({
    getData: build.query<getDataApiResponse, GetDataApiArg>({
      query: () => ({ 
        url: `/v1/data`,
        refetchOnMountOrArgChange: 600,
      }),
    }),
  },
})

So the injectedRtkApi.endpoints.getData.query key could be overridden using enhanceEndpoints

Maybe something like this would be possible:

import { injectedApi } from './generated/api'

const enhancedRtkApi = injectedApi.enhanceEndpoints({
    getData: {
      query: (args) => {
        injectedApi.endpoints.getData.query(
        {
          refetchOnMountOrArgChange: 600,
          ...args
         }
      }
      keepUnusedDataFor: 14400,
    },
  },
})

ericecook avatar May 17 '22 21:05 ericecook

const injectedRtkApi = api.injectEndpoints({
  endpoints: (build) => ({
    getData: build.query<getDataApiResponse, GetDataApiArg>({
      query: () => ({ 
        url: `/v1/data`,
-        refetchOnMountOrArgChange: 600,
      }),
+        refetchOnMountOrArgChange: 600,
    }),
  },
})

phryneas avatar May 17 '22 21:05 phryneas

I'm getting a TS error with that:

Argument of type '{ query: () => { url: string; }; refetchOnMountOrArgChange: number; }' is not assignable to parameter of type 'Omit<EndpointDefinitionWithQuery<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, {}>, DataResponse> & { ...; } & { ...; } & QueryExtraOptions<...>, "type"> | Omit<...>'.
  Object literal may only specify known properties, and 'refetchOnMountOrArgChange' does not exist in type 

ericecook avatar May 17 '22 22:05 ericecook

Yeah I re-checked the source - you can either define it for the full api, or on the hook call, but not on the endpoint. My bad.

phryneas avatar May 17 '22 22:05 phryneas

You can use it in useGetDataQuery as option: const {data, isLoading} = useGetDataQuery(args, {refetchOnMountOrArgChange: 600})

devoren avatar Sep 18 '22 17:09 devoren

Would like to +1 this item.

We use the codegen heavily and would like to be able to have the ability to override very specific endpoints.

mrnickel avatar Feb 06 '23 19:02 mrnickel

+1 for this as well please. For usage when you don't care where the endpoint is used, you just want the data to expire after X period. Would give a little bit more control.

McGern avatar Jun 09 '23 14:06 McGern

+1 This also seems like a good way of opting-out from using cached data for specific endpoint. Looks better than setting keepUnusedDataFor: 0. It would work great for scenarios when you don't want to use cached data for the endpoint at all, just refetch data when any of the endpoint arguments is changed or component using the query is mounted/remounted.

eclip5e avatar Nov 27 '23 20:11 eclip5e