Skip to content

Commit

Permalink
feat: add prefetch to all entities
Browse files Browse the repository at this point in the history
  • Loading branch information
dominik-stumpf committed Dec 6, 2024
1 parent cff8e91 commit 9975906
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 30 deletions.
19 changes: 4 additions & 15 deletions src/app/(dashboard)/[guildUrlName]/[pageUrlName]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { ScrollArea } from "@/components/ui/ScrollArea";
import { Skeleton } from "@/components/ui/Skeleton";
import { fetchGuildApiData } from "@/lib/fetchGuildApi";
import { roleBatchOptions } from "@/lib/options";
import { rewardBatchOptions, roleBatchOptions } from "@/lib/options";
import type { Schemas } from "@guildxyz/types";
import { Lock } from "@phosphor-icons/react/dist/ssr";
import { useSuspenseQuery } from "@tanstack/react-query";
Expand Down Expand Up @@ -40,19 +39,9 @@ const GuildPage = () => {
};

const RoleCard = ({ role }: { role: Schemas["Role"] }) => {
const { data: rewards } = useSuspenseQuery<Schemas["Reward"][]>({
queryKey: ["reward", "batch", role.id],
queryFn: () =>
fetchGuildApiData("reward/batch", {
method: "POST",
body: JSON.stringify({
ids: role.rewards?.map((r) => r.rewardId!) ?? [],
}),
headers: {
"Content-Type": "application/json",
},
}),
});
const { data: rewards } = useSuspenseQuery(
rewardBatchOptions({ roleId: role.id }),
);

return (
<Card className="flex flex-col md:flex-row" key={role.id}>
Expand Down
41 changes: 31 additions & 10 deletions src/app/(dashboard)/[guildUrlName]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getQueryClient } from "@/lib/getQueryClient";
import {
guildOptions,
pageBatchOptions,
rewardBatchOptions,
roleBatchOptions,
userOptions,
} from "@/lib/options";
Expand All @@ -16,28 +17,48 @@ import { JoinButton } from "./components/JoinButton";
const GuildLayout = async ({
params,
children,
}: PropsWithChildren<
DynamicRoute<{ guildUrlName: string; pageUrlName?: string }>
>) => {
const { guildUrlName, pageUrlName } = await params;
}: PropsWithChildren<DynamicRoute<{ guildUrlName: string }>>) => {
const { guildUrlName } = await params;
const queryClient = getQueryClient();

// TODO: handle possible request failures
await Promise.all([
queryClient.prefetchQuery(userOptions()),
queryClient.prefetchQuery(pageBatchOptions({ guildIdLike: guildUrlName })),
queryClient.prefetchQuery(
roleBatchOptions({
pageIdLike: pageUrlName || "",
guildIdLike: guildUrlName,
}),
),
queryClient.prefetchQuery(
guildOptions({
guildIdLike: guildUrlName,
}),
),
]);

const pageBatch = queryClient.getQueryData(
pageBatchOptions({ guildIdLike: guildUrlName }).queryKey,
);
const roleBatchOptionsCollection = pageBatch?.map((page) => {
return roleBatchOptions({
pageIdLike: page.urlName!,

Check warning on line 40 in src/app/(dashboard)/[guildUrlName]/layout.tsx

View workflow job for this annotation

GitHub Actions / quality-assurance

lint/style/noNonNullAssertion

Forbidden non-null assertion.
guildIdLike: guildUrlName,
});
});

if (roleBatchOptionsCollection) {
await Promise.all(
roleBatchOptionsCollection.map((c) => queryClient.prefetchQuery(c)),
);
const rewardBatchOptionsCollection = [];
for (const options of roleBatchOptionsCollection) {
const roles = queryClient.getQueryData(options.queryKey);
if (!roles) continue;
for (const { id } of roles) {
rewardBatchOptionsCollection.push(rewardBatchOptions({ roleId: id }));
}
}
await Promise.all(
rewardBatchOptionsCollection.map((c) => queryClient.prefetchQuery(c)),
);
}

const guild = queryClient.getQueryState(
guildOptions({
guildIdLike: guildUrlName,
Expand Down
24 changes: 21 additions & 3 deletions src/lib/fetchers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { fetchGuildApiData } from "@/lib/fetchGuildApi";
import { resolveIdLikeRequest } from "@/lib/resolveIdLikeRequest";
import { tryGetParsedToken } from "@/lib/token";
import type { Entity, EntitySchema, ErrorLike, WithIdLike } from "@/lib/types";
import type {
Entity,
EntitySchema,
ErrorLike,
WithId,
WithIdLike,
} from "@/lib/types";
import type { Schemas } from "@guildxyz/types";
import { z } from "zod";

export const fetchEntity = async <T extends Entity, Error = ErrorLike>({
idLike,
Expand Down Expand Up @@ -42,7 +49,7 @@ export const fetchPageBatch = async ({ guildIdLike }: WithIdLike<"guild">) => {
export const fetchRoleBatch = async ({
pageIdLike,
guildIdLike,
}: WithIdLike<"page"> & WithIdLike<"guild">) => {
}: Partial<WithIdLike<"page">> & WithIdLike<"guild">) => {
const isHomePageUrl = !pageIdLike;
let pageIdLikeWithHome = pageIdLike;
if (isHomePageUrl) {
Expand All @@ -54,11 +61,22 @@ export const fetchRoleBatch = async ({
}
const page = await fetchEntity({
entity: "page",
idLike: pageIdLikeWithHome,
idLike: pageIdLikeWithHome!,

Check warning on line 64 in src/lib/fetchers.ts

View workflow job for this annotation

GitHub Actions / quality-assurance

lint/style/noNonNullAssertion

Forbidden non-null assertion.
});

return fetchGuildApiData<Schemas["Role"][]>("role/batch", {
method: "POST",
body: JSON.stringify({ ids: page.roles?.map((p) => p.roleId!) ?? [] }),

Check warning on line 69 in src/lib/fetchers.ts

View workflow job for this annotation

GitHub Actions / quality-assurance

lint/style/noNonNullAssertion

Forbidden non-null assertion.
});
};

export const fetchRewardBatch = async ({ roleId }: WithId<"role">) => {
z.string().uuid().parse(roleId);
const role = await fetchEntity({ entity: "role", idLike: roleId });
return fetchGuildApiData<Schemas["Reward"][]>("reward/batch", {
method: "POST",
body: JSON.stringify({
ids: role.rewards?.map((r) => r.rewardId!) ?? [],

Check warning on line 79 in src/lib/fetchers.ts

View workflow job for this annotation

GitHub Actions / quality-assurance

lint/style/noNonNullAssertion

Forbidden non-null assertion.
}),
});
};
14 changes: 12 additions & 2 deletions src/lib/options.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {
fetchEntity,
fetchPageBatch,
fetchRewardBatch,
fetchRoleBatch,
fetchUser,
} from "@/lib/fetchers";
import type { WithIdLike } from "@/lib/types";
import type { WithId, WithIdLike } from "@/lib/types";
import type { Schemas } from "@guildxyz/types";
import { queryOptions } from "@tanstack/react-query";
import { z } from "zod";

export const entityOptions = ({
entity,
Expand Down Expand Up @@ -36,13 +38,21 @@ export const pageBatchOptions = ({ guildIdLike }: WithIdLike<"guild">) => {
export const roleBatchOptions = ({
pageIdLike,
guildIdLike,
}: WithIdLike<"page"> & WithIdLike<"guild">) => {
}: Partial<WithIdLike<"page">> & WithIdLike<"guild">) => {
return queryOptions({
queryKey: ["role", "batch", pageIdLike || "home", guildIdLike],
queryFn: () => fetchRoleBatch({ pageIdLike, guildIdLike }),
});
};

export const rewardBatchOptions = ({ roleId }: WithId<"role">) => {
z.string().uuid().parse(roleId);
return queryOptions({
queryKey: ["reward", "batch", roleId],
queryFn: () => fetchRewardBatch({ roleId }),
});
};

export const userOptions = () => {
return queryOptions<Schemas["User"]>({
queryKey: ["user"],
Expand Down
4 changes: 4 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export type WithIdLike<E extends Entity> = {
[key in `${E}IdLike`]: string;
};

export type WithId<E extends Entity> = {
[key in `${E}Id`]: string;
};

// TODO: move to @guildxyz/types
export type Entity = "guild" | "role" | "page" | "user" | "reward";

Expand Down

0 comments on commit 9975906

Please sign in to comment.