reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.55k stars 1.13k forks source link

rtk-query: Modify refetchOnMountOrArgChange with enhanceEndpoints #2333

Open ericecook opened 2 years ago

ericecook commented 2 years ago

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

phryneas commented 2 years ago

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

ericecook commented 2 years ago

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,
    },
  },
})
phryneas commented 2 years ago
const injectedRtkApi = api.injectEndpoints({
  endpoints: (build) => ({
    getData: build.query<getDataApiResponse, GetDataApiArg>({
      query: () => ({ 
        url: `/v1/data`,
-        refetchOnMountOrArgChange: 600,
      }),
+        refetchOnMountOrArgChange: 600,
    }),
  },
})
ericecook commented 2 years ago

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 
phryneas commented 2 years ago

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.

devoren commented 1 year ago

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

mrnickel commented 1 year ago

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.

McGern commented 1 year ago

+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.

eclip5e commented 7 months ago

+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.