Skip to content

Commit dc20b22

Browse files
author
ben.durrant
committed
Add selectCachedArgsForQuery util
1 parent 32e9081 commit dc20b22

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

packages/toolkit/src/query/core/buildSelectors.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import type {
55
RootState as _RootState,
66
RequestStatusFlags,
77
QueryCacheKey,
8+
QueryKeys,
9+
QueryState,
810
} from './apiState'
911
import { QueryStatus, getRequestStatusFlags } from './apiState'
1012
import type {
@@ -130,7 +132,12 @@ export function buildSelectors<
130132
const selectSkippedQuery = (state: RootState) => defaultQuerySubState
131133
const selectSkippedMutation = (state: RootState) => defaultMutationSubState
132134

133-
return { buildQuerySelector, buildMutationSelector, selectInvalidatedBy }
135+
return {
136+
buildQuerySelector,
137+
buildMutationSelector,
138+
selectInvalidatedBy,
139+
selectCachedArgsForQuery,
140+
}
134141

135142
function withRequestFlags<T extends { status: QueryStatus }>(
136143
substate: T
@@ -238,4 +245,22 @@ export function buildSelectors<
238245
})
239246
)
240247
}
248+
249+
function selectCachedArgsForQuery<QueryName extends QueryKeys<Definitions>>(
250+
state: RootState,
251+
queryName: QueryName
252+
): Array<QueryArgFrom<Definitions[QueryName]>> {
253+
return Object.values(state[reducerPath].queries as QueryState<any>)
254+
.filter(
255+
(
256+
entry
257+
): entry is Exclude<
258+
QuerySubState<Definitions[QueryName]>,
259+
{ status: QueryStatus.uninitialized }
260+
> =>
261+
entry?.endpointName === queryName &&
262+
entry.status !== QueryStatus.uninitialized
263+
)
264+
.map((entry) => entry.originalArgs)
265+
}
241266
}

packages/toolkit/src/query/core/module.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,16 @@ declare module '../apiTypes' {
356356
originalArgs: any
357357
queryCacheKey: string
358358
}>
359+
360+
/**
361+
* A function to select all arguments currently cached for a given endpoint.
362+
*
363+
* Can be used for mutations that want to do optimistic updates instead of invalidating a set of tags, but don't know exactly what they need to update.
364+
*/
365+
selectCachedArgsForQuery: <QueryName extends QueryKeys<Definitions>>(
366+
state: RootState<Definitions, string, ReducerPath>,
367+
queryName: QueryName
368+
) => Array<QueryArgFrom<Definitions[QueryName]>>
359369
}
360370
/**
361371
* Endpoints based on the input endpoints provided to `createApi`, containing `select` and `action matchers`.
@@ -527,13 +537,17 @@ export const coreModule = (): Module<CoreModule> => ({
527537

528538
safeAssign(api, { reducer: reducer as any, middleware })
529539

530-
const { buildQuerySelector, buildMutationSelector, selectInvalidatedBy } =
531-
buildSelectors({
532-
serializeQueryArgs: serializeQueryArgs as any,
533-
reducerPath,
534-
})
540+
const {
541+
buildQuerySelector,
542+
buildMutationSelector,
543+
selectInvalidatedBy,
544+
selectCachedArgsForQuery,
545+
} = buildSelectors({
546+
serializeQueryArgs: serializeQueryArgs as any,
547+
reducerPath,
548+
})
535549

536-
safeAssign(api.util, { selectInvalidatedBy })
550+
safeAssign(api.util, { selectInvalidatedBy, selectCachedArgsForQuery })
537551

538552
const {
539553
buildInitiateQuery,

packages/toolkit/src/query/tests/buildSelector.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,37 @@ describe('buildSelector', () => {
5252
const upperTitle = todoTitle.toUpperCase()
5353
expectExactType<string>(upperTitle)
5454
})
55+
test.skip('selectCachedArgsForQuery typetest', () => {
56+
interface Todo {
57+
userId: number
58+
id: number
59+
title: string
60+
completed: boolean
61+
}
62+
63+
type Todos = Array<Todo>
64+
65+
const exampleApi = createApi({
66+
reducerPath: 'api',
67+
baseQuery: fetchBaseQuery({
68+
baseUrl: 'https://jsonplaceholder.typicode.com',
69+
}),
70+
endpoints: (build) => ({
71+
getTodos: build.query<Todos, string>({
72+
query: () => '/todos',
73+
}),
74+
}),
75+
})
76+
77+
const store = configureStore({
78+
reducer: {
79+
[exampleApi.reducerPath]: exampleApi.reducer,
80+
other: () => 1,
81+
},
82+
})
83+
84+
expectExactType<string[]>(
85+
exampleApi.util.selectCachedArgsForQuery(store.getState(), 'getTodos')
86+
)
87+
})
5588
})

0 commit comments

Comments
 (0)