From ffafe6266b7d12278f74982ee0c7d396dfa142b8 Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Sun, 27 Oct 2024 18:30:21 +0000 Subject: [PATCH] Only pass initialPageParams option through query hook --- .../toolkit/src/query/react/buildHooks.ts | 44 +++-- .../src/query/tests/buildHooks.test.tsx | 151 ++++++++++++------ 2 files changed, 124 insertions(+), 71 deletions(-) diff --git a/packages/toolkit/src/query/react/buildHooks.ts b/packages/toolkit/src/query/react/buildHooks.ts index 4560cd7fb4..c6c509cc8f 100644 --- a/packages/toolkit/src/query/react/buildHooks.ts +++ b/packages/toolkit/src/query/react/buildHooks.ts @@ -758,7 +758,9 @@ export type LazyInfiniteQueryTrigger< ): InfiniteQueryActionCreatorResult } -interface UseInfiniteQuerySubscriptionOptions extends SubscriptionOptions { +interface UseInfiniteQuerySubscriptionOptions< + D extends InfiniteQueryDefinition, +> extends SubscriptionOptions { /** * Prevents a query from automatically running. * @@ -801,6 +803,7 @@ interface UseInfiniteQuerySubscriptionOptions extends SubscriptionOptions { * If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false. */ refetchOnMountOrArgChange?: boolean | number + initialPageParam?: PageParamFrom } export type TypedUseInfiniteQuerySubscription< @@ -852,19 +855,14 @@ export type UseInfiniteQuery< D extends InfiniteQueryDefinition, > = = UseInfiniteQueryStateDefaultResult>( arg: InfiniteQueryArgFrom | SkipToken, - options?: UseInfiniteQuerySubscriptionOptions & - UseInfiniteQueryStateOptions & - InfiniteQueryConfigOptions, PageParamFrom>, + options?: UseInfiniteQuerySubscriptionOptions & + UseInfiniteQueryStateOptions, ) => UseInfiniteQueryHookResult export type UseInfiniteQueryState< D extends InfiniteQueryDefinition, > = = UseInfiniteQueryStateDefaultResult>( arg: QueryArgFrom | SkipToken, - InfiniteQueryConfigOptions: InfiniteQueryConfigOptions< - ResultTypeFrom, - PageParamFrom - >, options?: UseInfiniteQueryStateOptions, ) => UseInfiniteQueryStateResult @@ -888,7 +886,7 @@ export type UseInfiniteQuerySubscription< D extends InfiniteQueryDefinition, > = ( arg: QueryArgFrom | SkipToken, - options?: UseInfiniteQuerySubscriptionOptions, + options?: UseInfiniteQuerySubscriptionOptions, ) => readonly [ LazyInfiniteQueryTrigger, QueryArgFrom | UninitializedValue, @@ -1706,6 +1704,7 @@ export function buildHooks({ skip = false, pollingInterval = 0, skipPollingIfUnfocused = false, + initialPageParam, } = {}, ) => { const { initiate } = api.endpoints[ @@ -1806,6 +1805,7 @@ export function buildHooks({ lastPromise?.unsubscribe() const promise = dispatch( initiate(stableArg, { + initialPageParam, subscriptionOptions: stableSubscriptionOptions, forceRefetch: refetchOnMountOrArgChange, }), @@ -1822,6 +1822,7 @@ export function buildHooks({ stableArg, stableSubscriptionOptions, subscriptionRemoved, + initialPageParam, ]) const subscriptionOptionsRef = useRef(stableSubscriptionOptions) @@ -1861,7 +1862,6 @@ export function buildHooks({ const useInfiniteQueryState: UseInfiniteQueryState = ( arg: any, - { getNextPageParam, getPreviousPageParam }, { skip = false, selectFromResult, trigger } = {}, ) => { const { select, initiate } = api.endpoints[ @@ -1932,22 +1932,14 @@ export function buildHooks({ useInfiniteQuerySubscription, useInfiniteQuery(arg, options) { const [trigger] = useInfiniteQuerySubscription(arg, options) - const queryStateResults = useInfiniteQueryState( - arg, - { - initialPageParam: options?.initialPageParam!, - getNextPageParam: options?.getNextPageParam!, - getPreviousPageParam: options?.getPreviousPageParam, - }, - { - selectFromResult: - arg === skipToken || options?.skip - ? undefined - : noPendingQueryStateSelector, - trigger, - ...options, - }, - ) + const queryStateResults = useInfiniteQueryState(arg, { + selectFromResult: + arg === skipToken || options?.skip + ? undefined + : noPendingQueryStateSelector, + trigger, + ...options, + }) const { data, diff --git a/packages/toolkit/src/query/tests/buildHooks.test.tsx b/packages/toolkit/src/query/tests/buildHooks.test.tsx index 0cbd53b756..c7076350a3 100644 --- a/packages/toolkit/src/query/tests/buildHooks.test.tsx +++ b/packages/toolkit/src/query/tests/buildHooks.test.tsx @@ -162,6 +162,8 @@ afterEach(() => { nextItemId = 0 amount = 0 listenerMiddleware.clearListeners() + + server.resetHandlers() }) let getRenderCount: () => number = () => 0 @@ -1498,6 +1500,14 @@ describe('hooks tests', () => { lastPageParam, allPageParams, ) => lastPageParam + 1, + getPreviousPageParam: ( + firstPage, + allPages, + firstPageParam, + allPageParams, + ) => { + return firstPageParam > 0 ? firstPageParam - 1 : undefined + }, }, query(pageParam) { return `https://example.com/listItems?page=${pageParam}` @@ -1507,57 +1517,66 @@ describe('hooks tests', () => { }) function PokemonList({ + arg = 'fire', initialPageParam = 0, }: { + arg?: string initialPageParam?: number }) { - const { data, isFetching, isUninitialized, fetchNextPage } = - pokemonApi.endpoints.getInfinitePokemon.useInfiniteQuery('a', { - initialPageParam, - getNextPageParam: ( - lastPage, - allPages, - // Page param type should be `number` - lastPageParam, - allPageParams, - ) => lastPageParam + 1, - }) + const { + data, + isFetching, + isUninitialized, + fetchNextPage, + fetchPreviousPage, + } = pokemonApi.endpoints.getInfinitePokemon.useInfiniteQuery(arg, { + initialPageParam, + }) + + const handlePreviousPage = async () => { + const res = await fetchPreviousPage() + } - const handleClick = async () => { - const promise = fetchNextPage() - const res = await promise + const handleNextPage = async () => { + const res = await fetchNextPage() } return (
{String(isUninitialized)}
{String(isFetching)}
+
Type: {arg}
- {data?.pages.map((page: any, i: number | null | undefined) => ( -
{JSON.stringify(page)}
+ {data?.pages.map((page, i: number | null | undefined) => ( +
{page.name}
))}
- +
) } - server.use( - http.get('https://example.com/listItems', ({ request }) => { - const url = new URL(request.url) - const pageString = url.searchParams.get('page') - const pageNum = parseInt(pageString || '0') - - const results: Pokemon = { - id: `${pageNum}`, - name: `Pokemon ${pageNum}`, - } + beforeEach(() => { + server.use( + http.get('https://example.com/listItems', ({ request }) => { + const url = new URL(request.url) + const pageString = url.searchParams.get('page') + const pageNum = parseInt(pageString || '0') + + const results: Pokemon = { + id: `${pageNum}`, + name: `Pokemon ${pageNum}`, + } - return HttpResponse.json(results) - }), - ) + return HttpResponse.json(results) + }), + ) + }) test('useInfiniteQuery fetchNextPage Trigger', async () => { const storeRef = setupApiStore(pokemonApi, undefined, { @@ -1567,34 +1586,76 @@ describe('hooks tests', () => { const checkNumQueries = (count: number) => { const cacheEntries = Object.keys(storeRef.store.getState().api.queries) const queries = cacheEntries.length - console.log('queries', queries, storeRef.store.getState().api.queries) + //console.log('queries', queries, storeRef.store.getState().api.queries) expect(queries).toBe(count) } - render(, { wrapper: storeRef.wrapper }) + const checkPageRows = (type: string, ids: number[]) => { + expect(screen.getByText(`Type: ${type}`)).toBeTruthy() + for (const id of ids) { + expect(screen.getByText(`Pokemon ${id}`)).toBeTruthy() + } + } + + async function waitForFetch() { + await waitFor(() => + expect(screen.getByTestId('isFetching').textContent).toBe('true'), + ) + await waitFor(() => + expect(screen.getByTestId('isFetching').textContent).toBe('false'), + ) + } + + const utils = render(, { wrapper: storeRef.wrapper }) expect(screen.getByTestId('data').textContent).toBe('') checkNumQueries(1) await waitFor(() => expect(screen.getByTestId('isUninitialized').textContent).toBe('false'), ) - await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false'), - ) + + // Initial load + await waitForFetch() + checkNumQueries(1) + checkPageRows('fire', [0]) + act(() => { fireEvent.click(screen.getByTestId('nextPage')) }) - await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false'), - ) - checkNumQueries(1) - await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false'), - ) - expect(screen.getByTestId('data').textContent).toBe( - '{"id":"0","name":"Pokemon 0"}{"id":"1","name":"Pokemon 1"}', - ) + + await waitForFetch() + + // Added one page + checkPageRows('fire', [0, 1]) + + act(() => { + fireEvent.click(screen.getByTestId('nextPage')) + }) + await waitForFetch() + + checkPageRows('fire', [0, 1, 2]) + + utils.rerender() + + await waitForFetch() + + checkNumQueries(2) + checkPageRows('water', [3]) + + act(() => { + fireEvent.click(screen.getByTestId('nextPage')) + }) + await waitForFetch() + + checkPageRows('water', [3, 4]) + + act(() => { + fireEvent.click(screen.getByTestId('prevPage')) + }) + await waitForFetch() + + checkPageRows('water', [2, 3, 4]) }) })