Skip to content

Commit 490c2d1

Browse files
authored
Merge pull request #2187 from wesen/bug/2186/fix-manually-initiated-rtk-query-promises-behaviour
2 parents a5e6587 + 478c935 commit 490c2d1

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { DefinitionType } from '../endpointDefinitions'
99
import type { QueryThunk, MutationThunk } from './buildThunks'
1010
import type { AnyAction, ThunkAction, SerializedError } from '@reduxjs/toolkit'
1111
import type { SubscriptionOptions, RootState } from './apiState'
12+
import { QueryStatus } from './apiState'
1213
import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
1314
import type { Api, ApiContext } from '../apiTypes'
1415
import type { ApiEndpointQuery } from './module'
@@ -274,17 +275,27 @@ Features like automatic cache collection, automatic refetching etc. will not be
274275
originalArgs: arg,
275276
queryCacheKey,
276277
})
278+
const selector = (
279+
api.endpoints[endpointName] as ApiEndpointQuery<any, any>
280+
).select(arg)
281+
277282
const thunkResult = dispatch(thunk)
283+
const stateAfter = selector(getState())
284+
278285
middlewareWarning(getState)
279286

280287
const { requestId, abort } = thunkResult
281288

289+
const skippedSynchronously = stateAfter.requestId !== requestId
290+
291+
const runningQuery = runningQueries[queryCacheKey]
292+
282293
const statePromise: QueryActionCreatorResult<any> = Object.assign(
283-
Promise.all([runningQueries[queryCacheKey], thunkResult]).then(() =>
284-
(api.endpoints[endpointName] as ApiEndpointQuery<any, any>).select(
285-
arg
286-
)(getState())
287-
),
294+
skippedSynchronously && !runningQuery
295+
? Promise.resolve(stateAfter)
296+
: Promise.all([runningQuery, thunkResult]).then(() =>
297+
selector(getState())
298+
),
288299
{
289300
arg,
290301
requestId,
@@ -328,7 +339,7 @@ Features like automatic cache collection, automatic refetching etc. will not be
328339
}
329340
)
330341

331-
if (!runningQueries[queryCacheKey]) {
342+
if (!runningQuery && !skippedSynchronously) {
332343
runningQueries[queryCacheKey] = statePromise
333344
statePromise.then(() => {
334345
delete runningQueries[queryCacheKey]
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { createApi } from '../core'
2+
import { fakeBaseQuery } from '../fakeBaseQuery'
3+
import { setupApiStore } from './helpers'
4+
5+
let calls = 0
6+
const api = createApi({
7+
baseQuery: fakeBaseQuery(),
8+
endpoints: (build) => ({
9+
increment: build.query<number, void>({
10+
async queryFn() {
11+
const data = calls++
12+
await Promise.resolve()
13+
return { data }
14+
},
15+
}),
16+
}),
17+
})
18+
19+
const storeRef = setupApiStore(api)
20+
21+
test('multiple synchonrous initiate calls with pre-existing cache entry', async () => {
22+
const { store, api } = storeRef
23+
// seed the store
24+
const firstValue = await store.dispatch(api.endpoints.increment.initiate())
25+
26+
expect(firstValue).toMatchObject({ data: 0, status: 'fulfilled' })
27+
28+
// dispatch another increment
29+
const secondValuePromise = store.dispatch(api.endpoints.increment.initiate())
30+
// and one with a forced refresh
31+
const thirdValuePromise = store.dispatch(
32+
api.endpoints.increment.initiate(undefined, { forceRefetch: true })
33+
)
34+
// and another increment
35+
const fourthValuePromise = store.dispatch(api.endpoints.increment.initiate())
36+
37+
const secondValue = await secondValuePromise
38+
const thirdValue = await thirdValuePromise
39+
const fourthValue = await fourthValuePromise
40+
41+
expect(secondValue).toMatchObject({
42+
data: firstValue.data,
43+
status: 'fulfilled',
44+
requestId: firstValue.requestId,
45+
})
46+
47+
expect(thirdValue).toMatchObject({ data: 1, status: 'fulfilled' })
48+
expect(thirdValue.requestId).not.toBe(firstValue.requestId)
49+
expect(fourthValue).toMatchObject({
50+
data: thirdValue.data,
51+
status: 'fulfilled',
52+
requestId: thirdValue.requestId,
53+
})
54+
})

0 commit comments

Comments
 (0)