Skip to content

Commit d11489c

Browse files
committed
Fix upsertQueryData for infinite queries
1 parent 23ab99a commit d11489c

File tree

3 files changed

+91
-32
lines changed

3 files changed

+91
-32
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export type QueryActionCreatorResult<
121121
export type InfiniteQueryActionCreatorResult<
122122
D extends InfiniteQueryDefinition<any, any, any, any, any>,
123123
> = Promise<InfiniteQueryResultSelectorResult<D>> & {
124-
arg: QueryArgFrom<D>
124+
arg: InfiniteQueryArgFrom<D>
125125
requestId: string
126126
subscriptionOptions: SubscriptionOptions | undefined
127127
abort(): void

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

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import type {
4646
} from './apiState'
4747
import { QueryStatus } from './apiState'
4848
import type {
49+
InfiniteQueryActionCreatorResult,
4950
QueryActionCreatorResult,
5051
StartInfiniteQueryActionCreatorOptions,
5152
StartQueryActionCreatorOptions,
@@ -201,51 +202,76 @@ type AllQueryKeys<Definitions extends EndpointDefinitions> =
201202
| QueryKeys<Definitions>
202203
| InfiniteQueryKeys<Definitions>
203204

204-
export type UpdateQueryDataThunk<
205+
type QueryArgFromAnyQueryDefinition<
205206
Definitions extends EndpointDefinitions,
206-
PartialState,
207-
> = <EndpointName extends AllQueryKeys<Definitions>>(
208-
endpointName: EndpointName,
209-
// TODO Find a way to deduplicate this ugly conditional type
210-
arg: Definitions[EndpointName] extends InfiniteQueryDefinition<
207+
EndpointName extends AllQueryKeys<Definitions>,
208+
> =
209+
Definitions[EndpointName] extends InfiniteQueryDefinition<
211210
any,
212211
any,
213212
any,
214213
any,
215214
any
216215
>
217216
? InfiniteQueryArgFrom<Definitions[EndpointName]>
218-
: QueryArgFrom<Definitions[EndpointName]>,
219-
updateRecipe: Recipe<
220-
Definitions[EndpointName] extends InfiniteQueryDefinition<
221-
any,
222-
any,
223-
any,
224-
any,
225-
any
226-
>
227-
? InfiniteData<
228-
ResultTypeFrom<Definitions[EndpointName]>,
229-
PageParamFrom<Definitions[EndpointName]>
230-
>
231-
: ResultTypeFrom<Definitions[EndpointName]>
232-
>,
217+
: Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
218+
? QueryArgFrom<Definitions[EndpointName]>
219+
: never
220+
221+
type DataFromAnyQueryDefinition<
222+
Definitions extends EndpointDefinitions,
223+
EndpointName extends AllQueryKeys<Definitions>,
224+
> =
225+
Definitions[EndpointName] extends InfiniteQueryDefinition<
226+
any,
227+
any,
228+
any,
229+
any,
230+
any
231+
>
232+
? InfiniteData<
233+
ResultTypeFrom<Definitions[EndpointName]>,
234+
PageParamFrom<Definitions[EndpointName]>
235+
>
236+
: Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
237+
? ResultTypeFrom<Definitions[EndpointName]>
238+
: unknown
239+
240+
type UpsertThunkResult<
241+
Definitions extends EndpointDefinitions,
242+
EndpointName extends AllQueryKeys<Definitions>,
243+
> =
244+
Definitions[EndpointName] extends InfiniteQueryDefinition<
245+
any,
246+
any,
247+
any,
248+
any,
249+
any
250+
>
251+
? InfiniteQueryActionCreatorResult<Definitions[EndpointName]>
252+
: Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
253+
? QueryActionCreatorResult<Definitions[EndpointName]>
254+
: QueryActionCreatorResult<never>
255+
256+
export type UpdateQueryDataThunk<
257+
Definitions extends EndpointDefinitions,
258+
PartialState,
259+
> = <EndpointName extends AllQueryKeys<Definitions>>(
260+
endpointName: EndpointName,
261+
arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>,
262+
updateRecipe: Recipe<DataFromAnyQueryDefinition<Definitions, EndpointName>>,
233263
updateProvided?: boolean,
234264
) => ThunkAction<PatchCollection, PartialState, any, UnknownAction>
235265

236266
export type UpsertQueryDataThunk<
237267
Definitions extends EndpointDefinitions,
238268
PartialState,
239-
> = <EndpointName extends QueryKeys<Definitions>>(
269+
> = <EndpointName extends AllQueryKeys<Definitions>>(
240270
endpointName: EndpointName,
241-
arg: QueryArgFrom<Definitions[EndpointName]>,
242-
value: ResultTypeFrom<Definitions[EndpointName]>,
271+
arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>,
272+
value: DataFromAnyQueryDefinition<Definitions, EndpointName>,
243273
) => ThunkAction<
244-
QueryActionCreatorResult<
245-
Definitions[EndpointName] extends QueryDefinition<any, any, any, any>
246-
? Definitions[EndpointName]
247-
: never
248-
>,
274+
UpsertThunkResult<Definitions, EndpointName>,
249275
PartialState,
250276
any,
251277
UnknownAction
@@ -397,7 +423,8 @@ export function buildThunks<
397423

398424
const upsertQueryData: UpsertQueryDataThunk<Definitions, State> =
399425
(endpointName, arg, value) => (dispatch) => {
400-
return dispatch(
426+
type EndpointName = typeof endpointName
427+
const res = dispatch(
401428
(
402429
api.endpoints[endpointName] as ApiEndpointQuery<
403430
QueryDefinition<any, any, any, any, any>,
@@ -410,7 +437,9 @@ export function buildThunks<
410437
data: value,
411438
}),
412439
}),
413-
)
440+
) as UpsertThunkResult<Definitions, EndpointName>
441+
442+
return res
414443
}
415444

416445
// The generic async payload function for all of our thunks
@@ -611,6 +640,14 @@ export function buildThunks<
611640
// Fetch first page
612641
result = await fetchPage(existingData, firstPageParam, maxPages)
613642

643+
if (forceQueryFn) {
644+
// HACK `upsertQueryData` expects the user to pass in the `{pages, pageParams}` structure,
645+
// but `fetchPage` treats that as `pages[0]`. We have to manually un-nest it.
646+
result = {
647+
data: (result.data as InfiniteData<unknown, unknown>).pages[0],
648+
} as QueryReturnValue
649+
}
650+
614651
// Fetch remaining pages
615652
for (let i = 1; i < totalPages; i++) {
616653
const param = getNextPageParam(

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,5 +568,27 @@ describe('Infinite queries', () => {
568568
],
569569
pageParams: [0, 1],
570570
})
571+
572+
const res2 = storeRef.store.dispatch(
573+
pokemonApi.util.upsertQueryData('getInfinitePokemon', 'water', {
574+
pages: [[{ id: '2', name: 'Pokemon 2' }]],
575+
pageParams: [2],
576+
}),
577+
)
578+
579+
const entry2InitialLoad = await res2
580+
const entry2Updated = pokemonApi.endpoints.getInfinitePokemon.select(
581+
'water',
582+
)(storeRef.store.getState())
583+
584+
console.log(
585+
'entry2Updated',
586+
util.inspect(entry2Updated, { depth: Infinity }),
587+
)
588+
589+
expect(entry2Updated.data).toEqual({
590+
pages: [[{ id: '2', name: 'Pokemon 2' }]],
591+
pageParams: [2],
592+
})
571593
})
572594
})

0 commit comments

Comments
 (0)