Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions packages/toolkit/src/query/core/buildThunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,12 +633,19 @@ export function buildThunks<
getState(),
arg.queryCacheKey,
)?.data as InfiniteData<unknown, unknown> | undefined
// Don't want to use `isForcedQuery` here, because that
// includes `refetchOnMountOrArgChange`.

// When the arg changes or the user forces a refetch,
// we don't include the `direction` flag. This lets us distinguish
// between actually refetching with a forced query, vs just fetching
// the next page.
const isForcedQueryNeedingRefetch = // arg.forceRefetch
isForcedQuery(arg, getState()) &&
!(arg as InfiniteQueryThunkArg<any>).direction
const existingData = (
arg.forceRefetch || !cachedData ? blankData : cachedData
isForcedQueryNeedingRefetch || !cachedData ? blankData : cachedData
) as InfiniteData<unknown, unknown>


// If the thunk specified a direction and we do have at least one page,
// fetch the next or previous page
if ('direction' in arg && arg.direction && existingData.pages.length) {
Expand Down
41 changes: 41 additions & 0 deletions packages/toolkit/src/query/tests/infiniteQueries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('Infinite queries', () => {
}

let counters: Record<string, number> = {}
let queryCounter = 0

const pokemonApi = createApi({
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
Expand Down Expand Up @@ -149,6 +150,7 @@ describe('Infinite queries', () => {
const url = new URL(request.url)
const pageString = url.searchParams.get('page')
const pageNum = parseInt(pageString || '0')
queryCounter++

const results: Pokemon[] = [
{ id: `${pageNum}`, name: `Pokemon ${pageNum}` },
Expand All @@ -168,6 +170,7 @@ describe('Infinite queries', () => {
counters = {}

hitCounter = 0
queryCounter = 0

process.env.NODE_ENV = 'development'
})
Expand Down Expand Up @@ -697,6 +700,44 @@ describe('Infinite queries', () => {
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])

expect(queryCounter).toBe(2)

const entry2InitialLoad = await storeRef.store.dispatch(
pokemonApiWithRefetch.endpoints.getInfinitePokemon.initiate('water', {}),
)

checkResultData(entry2InitialLoad, [[{ id: '0', name: 'Pokemon 0' }]])

expect(queryCounter).toBe(3)

const entry2SecondPage = await storeRef.store.dispatch(
pokemonApiWithRefetch.endpoints.getInfinitePokemon.initiate('water', {
direction: 'forward',
}),
)
checkResultData(entry2SecondPage, [
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])

expect(queryCounter).toBe(4)

// Should now be able to switch back to the first query.
// The hooks dispatch on arg change without a direction.
// That should trigger a refetch of the first query, meaning two requests.
// It should also _replace_ the existing results, rather than appending
// duplicate entries ([0, 1, 0, 1])
const entry1Refetched = await storeRef.store.dispatch(
pokemonApiWithRefetch.endpoints.getInfinitePokemon.initiate('fire', {}),
)

checkResultData(entry1Refetched, [
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])

expect(queryCounter).toBe(6)
})

test('Works with cache manipulation utils', async () => {
Expand Down
Loading