Skip to content

Commit

Permalink
Rework infinite query forced checks (#4854)
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson authored Feb 20, 2025
1 parent 36f1f64 commit 8a4ff3a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 3 deletions.
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

0 comments on commit 8a4ff3a

Please sign in to comment.