Skip to content

Commit 565f597

Browse files
phryneasmarkerikson
authored andcommitted
replace getRunningOperationPromise(s) with getRunning(Query|Queries|Mutation|Mutations)Thunk
1 parent a7fd57c commit 565f597

File tree

5 files changed

+175
-92
lines changed

5 files changed

+175
-92
lines changed

docs/rtk-query/api/created-api/api-slice-utils.mdx

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -249,53 +249,59 @@ Note that [hooks](./hooks.mdx) also track state in local component state and mig
249249
dispatch(api.util.resetApiState())
250250
```
251251

252-
## `getRunningOperationPromises`
252+
## `getRunningQueriesThunk` and `getRunningMutationsThunk`
253253

254254
#### Signature
255255

256256
```ts no-transpile
257-
getRunningOperationPromises: () => Array<Promise<unknown>>
257+
getRunningQueriesThunk(): ThunkWithReturnValue<Array<QueryActionCreatorResult<any>>>
258+
getRunningMutationsThunk(): ThunkWithReturnValue<Array<MutationActionCreatorResult<any>>>
258259
```
259260

260261
#### Description
261262

262-
A function that returns all promises for running queries and mutations.
263+
Thunks that (if dispatched) return either all running queries or mutations.
264+
These returned values can be awaited like promises.
263265

264-
This is useful for SSR scenarios to await everything triggered in any way, including via hook calls,
266+
This is useful for SSR scenarios to await all queries (or mutations) triggered in any way, including via hook calls
265267
or manually dispatching `initiate` actions.
266268

267-
```ts no-transpile title="Awaiting all currently running queries & mutations example"
268-
await Promise.all(api.util.getRunningOperationPromises())
269+
```ts no-transpile title="Awaiting all currently running queries example"
270+
await Promise.all(dispatch(api.util.getRunningQueriesThunk()))
269271
```
270272

271-
## `getRunningOperationPromise`
273+
## `getRunningQueryThunk` and `getRunningMutationThunk`
272274

273275
#### Signature
274276

275277
```ts no-transpile
276-
getRunningOperationPromise: <EndpointName extends QueryKeys<Definitions>>(
278+
getRunningQueryThunk<EndpointName extends QueryKeys<Definitions>>(
277279
endpointName: EndpointName,
278280
args: QueryArgFrom<Definitions[EndpointName]>
279-
) =>
280-
| QueryActionCreatorResult<Definitions[EndpointName]>
281+
): ThunkWithReturnValue<
282+
| QueryActionCreatorResult<
283+
Definitions[EndpointName] & { type: 'query' }
284+
>
281285
| undefined
286+
>
282287

283-
getRunningOperationPromise: <EndpointName extends MutationKeys<Definitions>>(
288+
getRunningMutationThunk<EndpointName extends MutationKeys<Definitions>>(
284289
endpointName: EndpointName,
285290
fixedCacheKeyOrRequestId: string
286-
) =>
287-
| MutationActionCreatorResult<Definitions[EndpointName]>
291+
): ThunkWithReturnValue<
292+
| MutationActionCreatorResult<
293+
Definitions[EndpointName] & { type: 'mutation' }
294+
>
288295
| undefined
296+
>
289297
```
290298

291299
#### Description
292300

293-
A function that returns a single promise for a given endpoint name + argument combination,
294-
if it is currently running. If it is not currently running, the function returns `undefined`.
301+
Thunks that (if dispatched) return a single running query (or mutation) for a given
302+
endpoint name + argument (or requestId/fixedCacheKey) combination, if it is currently running.
303+
If it is not currently running, the function returns `undefined`.
295304

296-
When used with mutation endpoints, it accepts a [fixed cache key](./hooks.mdx#signature-1)
297-
or request ID rather than the argument.
298-
299-
This is primarily added to add experimental support for suspense in the future.
300-
It enables writing custom hooks that look up if RTK Query has already got a running promise
301-
for a certain endpoint/argument combination, and retrieving that promise to `throw` it.
305+
These thunks are primarily added to add experimental support for suspense in the future.
306+
They enable writing custom hooks that look up if RTK Query has already got a running query/mutation
307+
for a certain endpoint/argument combination, and retrieving that to `throw` it as a promise.

docs/rtk-query/api/created-api/overview.mdx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,29 @@ type Api = {
5353
Array<TagTypes | FullTagDescription<TagTypes>>,
5454
string
5555
>
56-
resetApiState: SliceActions['resetApiState']
57-
getRunningOperationPromises: () => Array<Promise<unknown>>
58-
getRunningOperationPromise: <EndpointName extends QueryKeys<Definitions>>(
56+
selectInvalidatedBy: (
57+
state: FullState,
58+
tags: Array<TagTypes | FullTagDescription<TagTypes>>
59+
) => Array<{
60+
endpointName: string
61+
originalArgs: any
62+
queryCacheKey: string
63+
}>
64+
resetApiState: ActionCreator<ResetAction>
65+
getRunningQueryThunk(
5966
endpointName: EndpointName,
60-
args: QueryArgFrom<Definitions[EndpointName]>
61-
) =>
62-
| QueryActionCreatorResult<Definitions[EndpointName]>
63-
| undefined
64-
getRunningOperationPromise: <EndpointName extends MutationKeys<Definitions>>(
67+
args: QueryArg
68+
): ThunkWithReturnValue<QueryActionCreatorResult | undefined>
69+
getRunningMutationThunk(
6570
endpointName: EndpointName,
6671
fixedCacheKeyOrRequestId: string
67-
) =>
68-
| MutationActionCreatorResult<Definitions[EndpointName]>
69-
| undefined
72+
): ThunkWithReturnValue<MutationActionCreatorResult | undefined>
73+
getRunningQueriesThunk(): ThunkWithReturnValue<
74+
Array<QueryActionCreatorResult<any>>
75+
>
76+
getRunningMutationsThunk(): ThunkWithReturnValue<
77+
Array<MutationActionCreatorResult<any>>
78+
>
7079
}
7180

7281
// Internal actions

docs/rtk-query/usage/server-side-rendering.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The workflow is as follows:
2121
- Set up `next-redux-wrapper`
2222
- In `getStaticProps` or `getServerSideProps`:
2323
- Pre-fetch all queries via the `initiate` actions, e.g. `store.dispatch(api.endpoints.getPokemonByName.initiate(name))`
24-
- Wait for each query to finish using `await Promise.all(api.util.getRunningOperationPromises())`
24+
- Wait for each query to finish using `await Promise.all(dispatch(api.util.getRunningQueriesThunk()))`
2525
- In your `createApi` call, configure rehydration using the `extractRehydrationInfo` option:
2626

2727
[examples](docblock://query/createApi.ts?token=CreateApiOptions.extractRehydrationInfo)
@@ -56,4 +56,4 @@ The workflow is as follows:
5656
[examples](docblock://query/react/module.ts?token=ReactHooksModuleOptions.unstable__sideEffectsInRender)
5757

5858
- Use your custom `createApi` when calling `const api = createApi({...})`
59-
- Wait for all queries to finish using `await Promise.all(api.util.getRunningOperationPromises())` before performing the next render cycle
59+
- Wait for all queries to finish using `await Promise.all(dispatch(api.util.getRunningQueriesThunk()))` before performing the next render cycle

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

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import type { Api, ApiContext } from '../apiTypes'
1414
import type { ApiEndpointQuery } from './module'
1515
import type { BaseQueryError, QueryReturnValue } from '../baseQueryTypes'
1616
import type { QueryResultSelectorResult } from './buildSelectors'
17-
import { Dispatch } from 'redux'
17+
import type { Dispatch } from 'redux'
1818

1919
declare module './module' {
2020
export interface ApiEndpointQuery<
@@ -214,40 +214,53 @@ export function buildInitiate({
214214
return {
215215
buildInitiateQuery,
216216
buildInitiateMutation,
217-
getRunningOperationPromises,
218-
getRunningOperationPromise,
217+
getRunningQueryThunk,
218+
getRunningMutationThunk,
219+
getRunningQueriesThunk,
220+
getRunningMutationsThunk,
219221
}
220222

221-
function getRunningOperationPromise(
222-
endpointName: string,
223-
argOrRequestId: any
224-
): ThunkAction<any, any, any, AnyAction> {
223+
function getRunningQueryThunk(endpointName: string, queryArgs: any) {
225224
return (dispatch: Dispatch) => {
226225
const endpointDefinition = context.endpointDefinitions[endpointName]
227-
if (endpointDefinition.type === DefinitionType.query) {
228-
const queryCacheKey = serializeQueryArgs({
229-
queryArgs: argOrRequestId,
230-
endpointDefinition,
231-
endpointName,
232-
})
233-
return runningQueries.get(dispatch)?.[queryCacheKey]
234-
} else {
235-
return runningMutations.get(dispatch)?.[argOrRequestId]
236-
}
226+
const queryCacheKey = serializeQueryArgs({
227+
queryArgs,
228+
endpointDefinition,
229+
endpointName,
230+
})
231+
return runningQueries.get(dispatch)?.[queryCacheKey] as
232+
| QueryActionCreatorResult<never>
233+
| undefined
237234
}
238235
}
239236

240-
function getRunningOperationPromises(): ThunkAction<
241-
Promise<unknown>[],
242-
any,
243-
any,
244-
AnyAction
245-
> {
237+
function getRunningMutationThunk(
238+
/**
239+
* this is only here to allow TS to infer the result type by input value
240+
* we could use it to validate the result, but it's probably not necessary
241+
*/
242+
_endpointName: string,
243+
fixedCacheKeyOrRequestId: string
244+
) {
245+
return (dispatch: Dispatch) => {
246+
return runningMutations.get(dispatch)?.[fixedCacheKeyOrRequestId] as
247+
| MutationActionCreatorResult<never>
248+
| undefined
249+
}
250+
}
251+
252+
function getRunningQueriesThunk() {
253+
return (dispatch: Dispatch) =>
254+
Object.values(runningQueries.get(dispatch) || {}).filter(
255+
<T>(t: T | undefined): t is T => !!t
256+
)
257+
}
258+
259+
function getRunningMutationsThunk() {
246260
return (dispatch: Dispatch) =>
247-
[
248-
...Object.values(runningQueries.get(dispatch) || {}),
249-
...Object.values(runningMutations.get(dispatch) || {}),
250-
].filter(<T>(t: T | undefined): t is T => !!t)
261+
Object.values(runningMutations.get(dispatch) || {}).filter(
262+
<T>(t: T | undefined): t is T => !!t
263+
)
251264
}
252265

253266
function middlewareWarning(getState: () => RootState<{}, string, string>) {

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

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ export type CoreModule =
7171
| ReferenceQueryLifecycle
7272
| ReferenceCacheCollection
7373

74+
interface ThunkWithReturnValue<T>
75+
extends ThunkAction<T | undefined, any, any, AnyAction> {}
76+
7477
declare module '../apiTypes' {
7578
export interface ApiModules<
7679
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -138,47 +141,81 @@ declare module '../apiTypes' {
138141
*/
139142
util: {
140143
/**
141-
* Returns all promises for running queries and mutations.
142-
* Useful for SSR scenarios to await everything triggered in any way,
143-
* including via hook calls, or manually dispatching `initiate` actions.
144+
* This method had to be removed due to a conceptual bug in RTK.
145+
* Please see https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
146+
* @deprecated
144147
*/
145-
getRunningOperationPromises: () => ThunkAction<
146-
Array<Promise<unknown>>,
147-
any,
148-
any,
149-
AnyAction
150-
>
148+
getRunningOperationPromises: never // this is now types as `never` to immediately throw TS errors on use, but still allow for a comment
149+
151150
/**
152-
* If a promise is running for a given endpoint name + argument combination,
153-
* returns that promise. Otherwise, returns `undefined`.
154-
* Can be used to await a specific query/mutation triggered in any way,
155-
* including via hook calls, or manually dispatching `initiate` actions.
151+
* This method had to be removed due to a conceptual bug in RTK.
152+
* Please see https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
153+
* @deprecated
154+
*/
155+
getRunningOperationPromise: never // this is now types as `never` to immediately throw TS errors on use, but still allow for a comment
156+
157+
/**
158+
* A thunk that (if dispatched) will return a specific running query, identified
159+
* by `endpointName` and `args`.
160+
* If that query is not running, dispatching the thunk will result in `undefined`.
161+
*
162+
* Can be used to await a specific query triggered in any way,
163+
* including via hook calls or manually dispatching `initiate` actions.
164+
*
165+
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
156166
*/
157-
getRunningOperationPromise<EndpointName extends QueryKeys<Definitions>>(
167+
getRunningQueryThunk<EndpointName extends QueryKeys<Definitions>>(
158168
endpointName: EndpointName,
159169
args: QueryArgFrom<Definitions[EndpointName]>
160-
): ThunkAction<
170+
): ThunkWithReturnValue<
161171
| QueryActionCreatorResult<
162172
Definitions[EndpointName] & { type: 'query' }
163173
>
164-
| undefined,
165-
any,
166-
any,
167-
AnyAction
174+
| undefined
168175
>
169-
getRunningOperationPromise<
170-
EndpointName extends MutationKeys<Definitions>
171-
>(
176+
177+
/**
178+
* A thunk that (if dispatched) will return a specific running mutation, identified
179+
* by `endpointName` and `fixedCacheKey` or `requestId`.
180+
* If that mutation is not running, dispatching the thunk will result in `undefined`.
181+
*
182+
* Can be used to await a specific mutation triggered in any way,
183+
* including via hook trigger functions or manually dispatching `initiate` actions.
184+
*
185+
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
186+
*/
187+
getRunningMutationThunk<EndpointName extends MutationKeys<Definitions>>(
172188
endpointName: EndpointName,
173189
fixedCacheKeyOrRequestId: string
174-
): ThunkAction<
190+
): ThunkWithReturnValue<
175191
| MutationActionCreatorResult<
176192
Definitions[EndpointName] & { type: 'mutation' }
177193
>
178-
| undefined,
179-
any,
180-
any,
181-
AnyAction
194+
| undefined
195+
>
196+
197+
/**
198+
* A thunk that (if dispatched) will return all running queries.
199+
*
200+
* Useful for SSR scenarios to await all running queries triggered in any way,
201+
* including via hook calls or manually dispatching `initiate` actions.
202+
*
203+
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
204+
*/
205+
getRunningQueriesThunk(): ThunkWithReturnValue<
206+
Array<QueryActionCreatorResult<any>>
207+
>
208+
209+
/**
210+
* A thunk that (if dispatched) will return all running mutations.
211+
*
212+
* Useful for SSR scenarios to await all running mutations triggered in any way,
213+
* including via hook calls or manually dispatching `initiate` actions.
214+
*
215+
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
216+
*/
217+
getRunningMutationsThunk(): ThunkWithReturnValue<
218+
Array<MutationActionCreatorResult<any>>
182219
>
183220

184221
/**
@@ -307,6 +344,11 @@ declare module '../apiTypes' {
307344
string
308345
>
309346

347+
/**
348+
* A function to select all `{ endpointName, originalArgs, queryCacheKey }` combinations that would be invalidated by a specific set of tags.
349+
*
350+
* 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.
351+
*/
310352
selectInvalidatedBy: (
311353
state: RootState<Definitions, string, ReducerPath>,
312354
tags: ReadonlyArray<TagDescription<TagTypes>>
@@ -495,8 +537,10 @@ export const coreModule = (): Module<CoreModule> => ({
495537
const {
496538
buildInitiateQuery,
497539
buildInitiateMutation,
498-
getRunningOperationPromises,
499-
getRunningOperationPromise,
540+
getRunningMutationThunk,
541+
getRunningMutationsThunk,
542+
getRunningQueriesThunk,
543+
getRunningQueryThunk,
500544
} = buildInitiate({
501545
queryThunk,
502546
mutationThunk,
@@ -505,9 +549,20 @@ export const coreModule = (): Module<CoreModule> => ({
505549
context,
506550
})
507551

552+
function removedSSRHelper(): never {
553+
throw new Error(
554+
`This method had to be removed due to a conceptual bug in RTK.
555+
Please see https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.`
556+
)
557+
}
558+
508559
safeAssign(api.util, {
509-
getRunningOperationPromises,
510-
getRunningOperationPromise,
560+
getRunningOperationPromises: removedSSRHelper as any,
561+
getRunningOperationPromise: removedSSRHelper as any,
562+
getRunningMutationThunk,
563+
getRunningMutationsThunk,
564+
getRunningQueryThunk,
565+
getRunningQueriesThunk,
511566
})
512567

513568
return {

0 commit comments

Comments
 (0)