Skip to content

Commit 72f1015

Browse files
authored
Merge pull request #574 from get-convex/tom/useSessionPaginatedQuery
useSessionPaginatedQuery
2 parents 5e415c1 + 2fa9f61 commit 72f1015

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

convex/sessionsExample.ts

+12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
runSessionFunctions,
1717
vSessionId,
1818
} from "convex-helpers/server/sessions";
19+
import { paginationOptsValidator } from "convex/server";
1920
import { v } from "convex/values";
2021

2122
/** -----------------------------------------------------------------
@@ -193,3 +194,14 @@ export const joinRoom = mutationWithSession({
193194
}
194195
},
195196
});
197+
198+
export const paginatedQueryWithSession = query({
199+
args: { paginationOpts: paginationOptsValidator, ...SessionIdArg },
200+
handler: async (ctx, args) => {
201+
const foo = await ctx.db
202+
.query("presence")
203+
.order("desc")
204+
.paginate(args.paginationOpts);
205+
return foo;
206+
},
207+
});

packages/convex-helpers/react/sessions.ts

+51
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import type {
2828
FunctionReference,
2929
FunctionReturnType,
3030
OptionalRestArgs,
31+
PaginationOptions,
32+
PaginationResult,
3133
} from "convex/server";
3234
import {
3335
useQuery,
@@ -38,6 +40,9 @@ import {
3840
type MutationOptions,
3941
useConvex,
4042
type ReactMutation,
43+
usePaginatedQuery,
44+
type PaginatedQueryArgs,
45+
type UsePaginatedQueryReturnType,
4146
} from "convex/react";
4247
import type { SessionId } from "../server/sessions.js";
4348
import type { EmptyObject, BetterOmit } from "../index.js";
@@ -86,6 +91,21 @@ export type SessionArgsAndOptions<
8691
? [args?: EmptyObject, options?: Options]
8792
: [args: BetterOmit<FunctionArgs<Fn>, "sessionId">, options?: Options];
8893

94+
type SessionPaginatedQueryFunction<
95+
Args extends { paginationOpts: PaginationOptions } = {
96+
paginationOpts: PaginationOptions;
97+
},
98+
> = FunctionReference<
99+
"query",
100+
"public",
101+
{ sessionId: SessionId } & Args,
102+
PaginationResult<any>
103+
>;
104+
105+
export type SessionPaginatedQueryArgs<
106+
Fn extends SessionPaginatedQueryFunction,
107+
> = BetterOmit<PaginatedQueryArgs<Fn>, "sessionId"> | "skip";
108+
89109
/**
90110
* Context for a Convex session, creating a server session and providing the id.
91111
*
@@ -203,6 +223,37 @@ export function useSessionQuery<Query extends SessionFunction<"query">>(
203223
return useQuery(query, ...([newArgs] as OptionalRestArgs<Query>));
204224
}
205225

226+
/**
227+
* Use this in place of {@link usePaginatedQuery} to run a query, passing a sessionId.
228+
*
229+
* @param query Query that takes in a sessionId parameter. Like `api.foo.bar`.
230+
* @param args Args for that query, without the sessionId.
231+
* @param options - An object specifying the `initialNumItems` to be loaded in
232+
* the first page.
233+
* @returns A {@link UsePaginatedQueryRes} that includes the currently loaded
234+
* items, the status of the pagination, and a `loadMore` function.
235+
* For SSR, it will skip the query until the second render.
236+
*/
237+
export function useSessionPaginatedQuery<
238+
Query extends SessionPaginatedQueryFunction,
239+
>(
240+
query: Query,
241+
args: SessionPaginatedQueryArgs<Query>,
242+
options: { initialNumItems: number },
243+
): UsePaginatedQueryReturnType<Query> | undefined {
244+
const [sessionId] = useSessionId();
245+
const skip = args === "skip" || !sessionId;
246+
const originalArgs = args === "skip" ? {} : (args ?? {});
247+
248+
const newArgs = skip ? "skip" : { ...originalArgs, sessionId };
249+
250+
return usePaginatedQuery(
251+
query,
252+
newArgs as PaginatedQueryArgs<Query> | "skip",
253+
options,
254+
);
255+
}
256+
206257
type SessionMutation<Mutation extends FunctionReference<"mutation">> = (
207258
...args: SessionArgsArray<Mutation>
208259
) => Promise<FunctionReturnType<Mutation>>;

src/components/SessionsExample.tsx

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
useSessionId,
33
useSessionIdArg,
44
useSessionMutation,
5+
useSessionPaginatedQuery,
56
useSessionQuery,
67
} from "convex-helpers/react/sessions";
78
import { api } from "../../convex/_generated/api";
@@ -14,6 +15,11 @@ export default () => {
1415
const login = useSessionMutation(api.sessionsExample.logIn);
1516
const logout = useSessionMutation(api.sessionsExample.logOut);
1617
const myPresence = useSessionQuery(api.sessionsExample.myPresence);
18+
const paginatedPresence = useSessionPaginatedQuery(
19+
api.sessionsExample.paginatedQueryWithSession,
20+
{},
21+
{ initialNumItems: 2 },
22+
)!;
1723
const joinRoom = useSessionMutation(
1824
api.sessionsExample.joinRoom,
1925
).withOptimisticUpdate((store, args) => {
@@ -60,6 +66,17 @@ export default () => {
6066
</form>
6167
<p>{JSON.stringify(roomData)}</p>
6268
<ul>{myPresence && myPresence.map((room) => <li>{room}</li>)}</ul>
69+
<ul>
70+
{paginatedPresence.results.map((room) => (
71+
<li>{room.room}</li>
72+
))}
73+
</ul>
74+
<button
75+
disabled={paginatedPresence.status !== "CanLoadMore"}
76+
onClick={() => paginatedPresence.loadMore(2)}
77+
>
78+
load more
79+
</button>
6380

6481
<button onClick={() => refreshSessionId((newSessionId) => logout())}>
6582
Delete Session Data on Log Out

0 commit comments

Comments
 (0)