Skip to content

Commit

Permalink
feat: add two types of offset-based pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
patrikzita committed Jan 7, 2024
1 parent 64b7d47 commit 278ceb8
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 4 deletions.
Binary file modified sqlite.db
Binary file not shown.
8 changes: 8 additions & 0 deletions src/graphql/query/getDealsOffsetBased.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
query getDealsOffsetBased($limit: Float!, $offset: Float!) {
dealsOffsetBased(limit: $limit, offset: $offset) {
id
description
title
__typename
}
}
10 changes: 10 additions & 0 deletions src/graphql/query/getDealsOffsetBasedExpanded.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
query getDealsOffsetBasedExpanded($limitTotal: Float!, $offsetTotal: Float!) {
dealsOffsetBasedExpanded(limitTotal: $limitTotal, offsetTotal: $offsetTotal) {
deals {
description
id
title
}
totalCount
}
}
28 changes: 26 additions & 2 deletions src/graphql/schema/deals/deals.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { db } from "@/db/db";
import { deals as dbDeals } from "@/db/schema";
import { Query, Resolver } from "type-graphql";
import { Deal } from "./deals";
import { Arg, Query, Resolver } from "type-graphql";
import { Deal, DealsResponse } from "./deals";
import { count } from "drizzle-orm";

@Resolver(Deal)
export class DealResolver {
Expand All @@ -10,4 +11,27 @@ export class DealResolver {
const deals = db.select().from(dbDeals).all();
return deals;
}
@Query(() => [Deal])
async dealsOffsetBased(
@Arg("offset") offset: number,
@Arg("limit") limit: number
): Promise<Deal[]> {
const deals = await db.select().from(dbDeals).offset(offset).limit(limit);
return deals;
}

@Query(() => DealsResponse)
async dealsOffsetBasedExpanded(
@Arg("offsetTotal") offset: number,
@Arg("limitTotal") limit: number
): Promise<DealsResponse> {
const deals = await db.select().from(dbDeals).offset(offset).limit(limit);
const totalCountResult = await db.select({ value: count() }).from(dbDeals);
const totalCount = totalCountResult[0].value;

return {
deals,
totalCount,
};
}
}
9 changes: 9 additions & 0 deletions src/graphql/schema/deals/deals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,12 @@ export class Deal {
@Field()
description: string;
}

@ObjectType()
export class DealsResponse {
@Field(() => [Deal])
deals: Deal[];

@Field()
totalCount: number;
}
92 changes: 92 additions & 0 deletions src/pages/based-pagination/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
GetDealsOffsetBasedDocument,
GetDealsOffsetBasedExpandedDocument,
useGetDealsOffsetBasedExpandedQuery,
useGetDealsOffsetBasedQuery,
} from "@/generated/graphql";
import { addApolloState, initializeApollo } from "@/utils/apolloClient";

export default function BasedPagitanionPage() {
const { data, fetchMore, loading } = useGetDealsOffsetBasedExpandedQuery({
variables: {
limitTotal: 3,
offsetTotal: 0,
},
});

/* const { data, fetchMore } = useGetDealsOffsetBasedQuery({
variables: {
limit: 3,
offset: 0,
},
}); */

/* const loadMore = () => {
const currentLength = data.dealsOffsetBased.length || 0;
console.log(currentLength);
fetchMore({
variables: {
offset: currentLength,
limit: 3,
},
});
}; */

const loadMore = () => {
const currentLength = data.dealsOffsetBasedExpanded.deals.length || 0;
console.log(currentLength);
fetchMore({
variables: {
offsetTotal: currentLength,
limitTotal: 3,
},
});
};

console.log(data);
if (loading) {
return <div>loading</div>;
}

return (
<main>
<div>
{data.dealsOffsetBasedExpanded.deals &&
data.dealsOffsetBasedExpanded.deals.map((deal) => (
<div key={deal.id}>
<h1>{deal.title}</h1>
</div>
))}
{/* {data.dealsOffsetBased.deals.map((deal) => (
<div key={deal.id}>
<h1>{deal.title}</h1>
</div>
))} */}
<button onClick={loadMore}>Načíst další</button>
</div>
</main>
);
}

export async function getServerSideProps() {
const apolloClient = initializeApollo();

/* await apolloClient.query({
query: GetDealsOffsetBasedDocument,
variables: {
limit: 3,
offset: 0,
},
}); */
/* await apolloClient.query({
query: GetDealsOffsetBasedExpandedDocument,
variables: {
limitTotal: 3,
offsetTotal: 0,
},
}); */

return addApolloState(apolloClient, {
props: {},
});
}
61 changes: 59 additions & 2 deletions src/utils/apolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import {
from,
} from "@apollo/client";
import { onError } from "@apollo/client/link/error";
import {
concatPagination,
offsetLimitPagination,
} from "@apollo/client/utilities";
import merge from "deepmerge";
import isEqual from "lodash/isEqual";
import { useMemo } from "react";
Expand Down Expand Up @@ -33,8 +37,32 @@ function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: from([errorLink, httpLink]),
connectToDevTools: process.env.NODE_ENV === "development",
cache: new InMemoryCache(),
connectToDevTools: true,
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
dealsOffsetBasedExpanded: {
keyArgs: false, // None of the arguments will be used to generate a separate cache entry
merge(existing, incoming, { args: { offsetTotal = 0 } }) {
// Combines the incoming list of deals with the existing list

const mergedDeals = existing ? existing.deals.slice(0) : [];
for (let i = 0; i < incoming.deals.length; i++) {
mergedDeals[offsetTotal + i] = incoming.deals[i];
}

return {
...existing,
deals: mergedDeals,
totalCount: incoming.totalCount, // Assumes totalCount is updated with each query
};
},
},
},
},
},
}),
});
}

Expand Down Expand Up @@ -85,3 +113,32 @@ export function useApollo(pageProps) {
const store = useMemo(() => initializeApollo(state), [state]);
return store;
}

/* cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
dealsOffsetBasedExpanded: {
keyArgs: false, // None of the arguments will be used to generate a separate cache entry
merge(existing, incoming, { args: { offsetTotal = 0 } }) {
// Combines the incoming list of deals with the existing list
const mergedDeals = existing ? existing.deals.slice(0) : [];
for (let i = 0; i < incoming.deals.length; ++i) {
mergedDeals[offsetTotal + i] = incoming.deals[i];
}
// Returns the combined list of deals and the most recent total count
return {
...existing,
deals: mergedDeals,
totalCount: incoming.totalCount, // Assumes totalCount is updated with each query
};
},
// The read function is not strictly necessary here unless you need to restructure the returned data
read(existing) {
return existing;
},
},
},
},
},
}), */

0 comments on commit 278ceb8

Please sign in to comment.