Skip to content

Commit 5742f4f

Browse files
committed
Add pageParamName
1 parent 78115c5 commit 5742f4f

File tree

2 files changed

+99
-7
lines changed

2 files changed

+99
-7
lines changed

Diff for: packages/openapi-react-query/src/index.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
type UseQueryOptions,
55
type UseQueryResult,
66
type InfiniteData,
7-
type InfiniteQueryObserverResult,
87
type UseInfiniteQueryOptions,
98
type UseInfiniteQueryResult,
109
type UseSuspenseQueryOptions,
@@ -116,7 +115,9 @@ export type UseInfiniteQueryMethod<Paths extends Record<string, Record<HttpMetho
116115
unknown
117116
>,
118117
"queryKey" | "queryFn"
119-
>,
118+
> & {
119+
pageParamName?: string;
120+
},
120121
>(
121122
method: Method,
122123
url: Path,
@@ -198,8 +199,10 @@ export default function createClient<Paths extends {}, Media extends MediaType =
198199
useQuery(queryOptions(method, path, init as InitWithUnknowns<typeof init>, options), queryClient),
199200
useSuspenseQuery: (method, path, ...[init, options, queryClient]) =>
200201
useSuspenseQuery(queryOptions(method, path, init as InitWithUnknowns<typeof init>, options), queryClient),
201-
useInfiniteQuery: (method, path, init, options, queryClient) =>
202-
useInfiniteQuery(
202+
useInfiniteQuery: (method, path, init, options, queryClient) => {
203+
const { pageParamName = "cursor", ...restOptions } = options;
204+
205+
return useInfiniteQuery(
203206
{
204207
queryKey: [method, path, init] as const,
205208
queryFn: async <Method extends HttpMethod, Path extends PathsWithMethod<Paths, Method>>({
@@ -216,7 +219,7 @@ export default function createClient<Paths extends {}, Media extends MediaType =
216219
...(init?.params || {}),
217220
query: {
218221
...(init?.params as { query?: DefaultParamsOption })?.query,
219-
cursor: pageParam,
222+
[pageParamName]: pageParam,
220223
},
221224
},
222225
};
@@ -227,10 +230,11 @@ export default function createClient<Paths extends {}, Media extends MediaType =
227230
}
228231
return data;
229232
},
230-
...options,
233+
...restOptions,
231234
},
232235
queryClient,
233-
),
236+
);
237+
},
234238
useMutation: (method, path, options, queryClient) =>
235239
useMutation(
236240
{

Diff for: packages/openapi-react-query/test/index.test.tsx

+88
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ describe("client", () => {
822822
});
823823
});
824824
});
825+
// >: {"tests": ["infiniteQuery"]}
825826
describe("useInfiniteQuery", () => {
826827
it("should fetch data correctly with pagination and include cursor", async () => {
827828
const fetchClient = createFetchClient<paths>({ baseUrl });
@@ -990,5 +991,92 @@ describe("client", () => {
990991
const allItems = result.current.data?.pages.flatMap((page) => page.items);
991992
expect(allItems).toEqual([4, 5, 6, 1, 2, 3]);
992993
});
994+
it("should use custom cursor params", async () => {
995+
const fetchClient = createFetchClient<paths>({ baseUrl });
996+
const client = createClient(fetchClient);
997+
998+
// First page request handler
999+
const firstRequestHandler = useMockRequestHandler({
1000+
baseUrl,
1001+
method: "get",
1002+
path: "/paginated-data",
1003+
status: 200,
1004+
body: { items: [1, 2, 3], nextPage: 1 },
1005+
});
1006+
1007+
const { result, rerender } = renderHook(
1008+
() =>
1009+
client.useInfiniteQuery(
1010+
"get",
1011+
"/paginated-data",
1012+
{
1013+
params: {
1014+
query: {
1015+
limit: 3,
1016+
},
1017+
},
1018+
},
1019+
{
1020+
getNextPageParam: (lastPage) => lastPage.nextPage,
1021+
initialPageParam: 0,
1022+
pageParamName: "follow_cursor",
1023+
},
1024+
),
1025+
{ wrapper },
1026+
);
1027+
1028+
// Wait for initial query to complete
1029+
await waitFor(() => expect(result.current.isSuccess).toBe(true));
1030+
1031+
// Verify first request
1032+
const firstRequestUrl = firstRequestHandler.getRequestUrl();
1033+
expect(firstRequestUrl?.searchParams.get("limit")).toBe("3");
1034+
expect(firstRequestUrl?.searchParams.get("follow_cursor")).toBe("0");
1035+
1036+
// Set up mock for second page before triggering next page fetch
1037+
const secondRequestHandler = useMockRequestHandler({
1038+
baseUrl,
1039+
method: "get",
1040+
path: "/paginated-data",
1041+
status: 200,
1042+
body: { items: [4, 5, 6], nextPage: 2 },
1043+
});
1044+
1045+
// Fetch next page
1046+
await act(async () => {
1047+
await result.current.fetchNextPage();
1048+
// Force a rerender to ensure state is updated
1049+
rerender();
1050+
});
1051+
1052+
// Wait for second page to be fetched and verify loading states
1053+
await waitFor(() => {
1054+
expect(result.current.isFetching).toBe(false);
1055+
expect(result.current.hasNextPage).toBe(true);
1056+
expect(result.current.data?.pages).toHaveLength(2);
1057+
});
1058+
1059+
// Verify second request
1060+
const secondRequestUrl = secondRequestHandler.getRequestUrl();
1061+
expect(secondRequestUrl?.searchParams.get("limit")).toBe("3");
1062+
expect(secondRequestUrl?.searchParams.get("follow_cursor")).toBe("1");
1063+
1064+
expect(result.current.data).toBeDefined();
1065+
expect(result.current.data?.pages[0].nextPage).toBe(1);
1066+
1067+
expect(result.current.data).toBeDefined();
1068+
expect(result.current.data?.pages[1].nextPage).toBe(2);
1069+
1070+
// Verify the complete data structure
1071+
expect(result.current.data?.pages).toEqual([
1072+
{ items: [1, 2, 3], nextPage: 1 },
1073+
{ items: [4, 5, 6], nextPage: 2 },
1074+
]);
1075+
1076+
// Verify we can access all items through pages
1077+
const allItems = result.current.data?.pages.flatMap((page) => page.items);
1078+
expect(allItems).toEqual([1, 2, 3, 4, 5, 6]);
1079+
});
9931080
});
1081+
// <: {"tests": ["infiniteQuery"]}
9941082
});

0 commit comments

Comments
 (0)