From d9c46d2431b9e5911ae45b4639735b42a88730a3 Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Wed, 4 Dec 2024 15:38:12 +0100 Subject: [PATCH] refactor: use tanstack query on explorer --- .../explorer/components/AssociatedGuilds.tsx | 40 ++++++++++ .../components/InfiniteScrollGuilds.tsx | 15 +--- .../explorer/{actions.ts => fetchers.ts} | 10 ++- src/app/(dashboard)/explorer/layout.tsx | 21 ++++++ src/app/(dashboard)/explorer/options.ts | 23 ++++++ src/app/(dashboard)/explorer/page.tsx | 74 ++----------------- 6 files changed, 103 insertions(+), 80 deletions(-) create mode 100644 src/app/(dashboard)/explorer/components/AssociatedGuilds.tsx rename src/app/(dashboard)/explorer/{actions.ts => fetchers.ts} (52%) create mode 100644 src/app/(dashboard)/explorer/layout.tsx create mode 100644 src/app/(dashboard)/explorer/options.ts diff --git a/src/app/(dashboard)/explorer/components/AssociatedGuilds.tsx b/src/app/(dashboard)/explorer/components/AssociatedGuilds.tsx new file mode 100644 index 0000000000..2d278c316b --- /dev/null +++ b/src/app/(dashboard)/explorer/components/AssociatedGuilds.tsx @@ -0,0 +1,40 @@ +"use client"; + +import { useSuspenseQuery } from "@tanstack/react-query"; +import { associatedGuildsOption } from "../options"; +import { CreateGuildLink } from "./CreateGuildLink"; +import { GuildCard, GuildCardSkeleton } from "./GuildCard"; + +export const AssociatedGuilds = () => { + const { data: associatedGuilds } = useSuspenseQuery(associatedGuildsOption()); + + return associatedGuilds.length > 0 ? ( +
+ {associatedGuilds.map((guild) => ( + + ))} +
+ ) : ( +
+ Guild Robot + +

+ You're not a member of any guilds yet. Explore and join some below, + or create your own! +

+ + +
+ ); +}; + +export const AssociatedGuildsSkeleton = () => { + return ( +
+ {Array.from({ length: 3 }, (_, i) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: + + ))} +
+ ); +}; diff --git a/src/app/(dashboard)/explorer/components/InfiniteScrollGuilds.tsx b/src/app/(dashboard)/explorer/components/InfiniteScrollGuilds.tsx index dc3df58e4b..4078a7b89d 100644 --- a/src/app/(dashboard)/explorer/components/InfiniteScrollGuilds.tsx +++ b/src/app/(dashboard)/explorer/components/InfiniteScrollGuilds.tsx @@ -4,26 +4,15 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import { useIntersection } from "foxact/use-intersection"; import { useAtomValue } from "jotai"; import { useCallback, useEffect } from "react"; -import { getGuildSearch } from "../actions"; import { searchAtom } from "../atoms"; import { PAGE_SIZE } from "../constants"; +import { guildSearchOptions } from "../options"; import { GuildCard, GuildCardSkeleton } from "./GuildCard"; export const InfiniteScrollGuilds = () => { const search = useAtomValue(searchAtom); const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = - useInfiniteQuery({ - queryKey: ["guilds", search || ""], - queryFn: ({ pageParam }) => - getGuildSearch({ search: search || "", pageParam }), - initialPageParam: 1, - staleTime: Number.POSITIVE_INFINITY, - enabled: search !== undefined, - getNextPageParam: (lastPage) => - lastPage.total / lastPage.pageSize <= lastPage.page - ? undefined - : lastPage.page + 1, - }); + useInfiniteQuery(guildSearchOptions({ search })); const [setIntersection, isIntersected, resetIsIntersected] = useIntersection({ rootMargin: "700px", diff --git a/src/app/(dashboard)/explorer/actions.ts b/src/app/(dashboard)/explorer/fetchers.ts similarity index 52% rename from src/app/(dashboard)/explorer/actions.ts rename to src/app/(dashboard)/explorer/fetchers.ts index c7f1184f5b..f9e275d2f1 100644 --- a/src/app/(dashboard)/explorer/actions.ts +++ b/src/app/(dashboard)/explorer/fetchers.ts @@ -1,9 +1,17 @@ import { fetchGuildApiData } from "@/lib/fetchGuildApi"; +import { tryGetParsedToken } from "@/lib/token"; import type { PaginatedResponse } from "@/lib/types"; import type { Schemas } from "@guildxyz/types"; import { PAGE_SIZE } from "./constants"; -export const getGuildSearch = async ({ +export const fetchAssociatedGuilds = async () => { + const { userId } = await tryGetParsedToken(); + return fetchGuildApiData>( + `guild/search?page=1&pageSize=${Number.MAX_SAFE_INTEGER}&sortBy=name&reverse=false&customQuery=@owner:{${userId}}`, + ); +}; + +export const fetchGuildSearch = async ({ pageParam, search, }: { pageParam: number; search: string }) => { diff --git a/src/app/(dashboard)/explorer/layout.tsx b/src/app/(dashboard)/explorer/layout.tsx new file mode 100644 index 0000000000..8937d8e7f1 --- /dev/null +++ b/src/app/(dashboard)/explorer/layout.tsx @@ -0,0 +1,21 @@ +import { getQueryClient } from "@/lib/getQueryClient"; +import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; +import type { PropsWithChildren } from "react"; +import { associatedGuildsOption, guildSearchOptions } from "./options"; + +const ExplorerLayout = async ({ children }: PropsWithChildren) => { + const queryClient = getQueryClient(); + void queryClient.prefetchInfiniteQuery( + guildSearchOptions({}), + //queryFn: () => fetchGuildSearch({ search: "", pageParam: 1 }), + ); + void queryClient.prefetchQuery(associatedGuildsOption()); + + return ( + + {children} + + ); +}; + +export default ExplorerLayout; diff --git a/src/app/(dashboard)/explorer/options.ts b/src/app/(dashboard)/explorer/options.ts new file mode 100644 index 0000000000..95e3cad38e --- /dev/null +++ b/src/app/(dashboard)/explorer/options.ts @@ -0,0 +1,23 @@ +import { infiniteQueryOptions, queryOptions } from "@tanstack/react-query"; +import { fetchAssociatedGuilds, fetchGuildSearch } from "./fetchers"; + +export const associatedGuildsOption = () => { + return queryOptions({ + queryKey: ["associatedGuilds"], + queryFn: () => fetchAssociatedGuilds(), + select: (data) => data.items, + }); +}; + +export const guildSearchOptions = ({ search = "" }: { search?: string }) => { + return infiniteQueryOptions({ + queryKey: ["guilds", search], + queryFn: ({ pageParam }) => fetchGuildSearch({ search: search, pageParam }), + initialPageParam: 1, + enabled: search !== undefined, + getNextPageParam: (lastPage) => + lastPage.total / lastPage.pageSize <= lastPage.page + ? undefined + : lastPage.page + 1, + }); +}; diff --git a/src/app/(dashboard)/explorer/page.tsx b/src/app/(dashboard)/explorer/page.tsx index e429bbab0e..4359238757 100644 --- a/src/app/(dashboard)/explorer/page.tsx +++ b/src/app/(dashboard)/explorer/page.tsx @@ -1,37 +1,18 @@ import { AuthBoundary } from "@/components/AuthBoundary"; import { SignInButton } from "@/components/SignInButton"; -import { fetchGuildApiData } from "@/lib/fetchGuildApi"; -import { getQueryClient } from "@/lib/getQueryClient"; -import { tryGetParsedToken } from "@/lib/token"; -import type { PaginatedResponse } from "@/lib/types"; -import type { Schemas } from "@guildxyz/types"; -import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; import { Suspense } from "react"; -import { getGuildSearch } from "./actions"; +import { + AssociatedGuilds, + AssociatedGuildsSkeleton, +} from "./components/AssociatedGuilds"; import { CreateGuildLink } from "./components/CreateGuildLink"; -import { GuildCard, GuildCardSkeleton } from "./components/GuildCard"; import { HeaderBackground } from "./components/HeaderBackground"; import { InfiniteScrollGuilds } from "./components/InfiniteScrollGuilds"; import { StickyNavbar } from "./components/StickyNavbar"; import { StickySearch } from "./components/StickySearch"; import { ACTIVE_SECTION } from "./constants"; -const getAssociatedGuilds = async () => { - const { userId } = await tryGetParsedToken(); - - return fetchGuildApiData>( - `guild/search?page=1&pageSize=${Number.MAX_SAFE_INTEGER}&sortBy=name&reverse=false&customQuery=@owner:{${userId}}`, - ); -}; - -export default async function Explorer() { - const queryClient = getQueryClient(); - await queryClient.prefetchInfiniteQuery({ - queryKey: ["guilds", ""], - initialPageParam: 1, - queryFn: () => getGuildSearch({ search: "", pageParam: 1 }), - }); - +const Explorer = async () => { return ( <>
- - - + ); -} +}; async function AssociatedGuildsSection() { return ( @@ -107,41 +86,4 @@ async function AssociatedGuildsSection() { ); } -async function AssociatedGuilds() { - let associatedGuilds: Schemas["Guild"][]; - try { - associatedGuilds = (await getAssociatedGuilds()).items; - } catch { - return; - } - - return associatedGuilds.length > 0 ? ( -
- {associatedGuilds.map((guild) => ( - - ))} -
- ) : ( -
- Guild Robot - -

- You're not a member of any guilds yet. Explore and join some below, - or create your own! -

- - -
- ); -} - -function AssociatedGuildsSkeleton() { - return ( -
- {Array.from({ length: 3 }, (_, i) => ( - // biome-ignore lint/suspicious/noArrayIndexKey: - - ))} -
- ); -} +export default Explorer;