diff --git a/src/app/(pages)/(home)/_components/bookmark-list.tsx b/src/app/(pages)/(home)/_components/bookmark-list.tsx index ee08de8..6c04afe 100644 --- a/src/app/(pages)/(home)/_components/bookmark-list.tsx +++ b/src/app/(pages)/(home)/_components/bookmark-list.tsx @@ -3,8 +3,9 @@ import { BookmarkCard } from "./bookmark-card"; import BlurFade from "~/app/_core/components/blur-fade"; import { useBookmarkStore } from "../_state/store/use-bookmark-store"; -import { useQuery } from "@tanstack/react-query"; + import { bookmarksQueries } from "../_state/queries/bookmark-query"; +import { useQuery } from "@tanstack/react-query"; export function BookmarkList() { const { activeBookmarkId } = useBookmarkStore(); diff --git a/src/app/(pages)/(home)/_state/mutations/use-create-bookmark-mutation.tsx b/src/app/(pages)/(home)/_state/mutations/use-create-bookmark-mutation.tsx index 422c0e1..f366fc9 100644 --- a/src/app/(pages)/(home)/_state/mutations/use-create-bookmark-mutation.tsx +++ b/src/app/(pages)/(home)/_state/mutations/use-create-bookmark-mutation.tsx @@ -1,11 +1,11 @@ import { useMutation } from "@tanstack/react-query"; import { type createBookmark } from "~/server/queries/bookmark"; import { bookmarkService } from "../../services/bookmark-service"; -import { useQueryClient } from "@tanstack/react-query"; import { bookmarksQueries } from "../queries/bookmark-query"; +import { getQueryClient } from "~/app/_core/utils/get-query-client"; export const useCreateBookmarkMutation = () => { - const queryClient = useQueryClient(); + const queryClient = getQueryClient(); return useMutation({ mutationFn: (bookmark: Parameters[0]) => diff --git a/src/app/(pages)/(home)/_state/mutations/use-delete-bookmark-mutation.tsx b/src/app/(pages)/(home)/_state/mutations/use-delete-bookmark-mutation.tsx index a6997dd..8cace77 100644 --- a/src/app/(pages)/(home)/_state/mutations/use-delete-bookmark-mutation.tsx +++ b/src/app/(pages)/(home)/_state/mutations/use-delete-bookmark-mutation.tsx @@ -1,10 +1,10 @@ import { useMutation } from "@tanstack/react-query"; import { bookmarkService } from "../../services/bookmark-service"; -import { useQueryClient } from "@tanstack/react-query"; import { bookmarksQueries } from "../queries/bookmark-query"; +import { getQueryClient } from "~/app/_core/utils/get-query-client"; export const useDeleteBookmarkMutation = () => { - const queryClient = useQueryClient(); + const queryClient = getQueryClient(); return useMutation({ mutationFn: (id: number) => bookmarkService.deleteBookmark(id), diff --git a/src/app/(pages)/(home)/_state/mutations/use-update-bookmark-mutation.tsx b/src/app/(pages)/(home)/_state/mutations/use-update-bookmark-mutation.tsx index 4d59792..b6e130d 100644 --- a/src/app/(pages)/(home)/_state/mutations/use-update-bookmark-mutation.tsx +++ b/src/app/(pages)/(home)/_state/mutations/use-update-bookmark-mutation.tsx @@ -1,13 +1,14 @@ -import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { useMutation } from "@tanstack/react-query"; import { type updateBookmark } from "~/server/queries/bookmark"; import { bookmarkService } from "../../services/bookmark-service"; import { bookmarksQueries } from "../queries/bookmark-query"; +import { getQueryClient } from "~/app/_core/utils/get-query-client"; export const updateBookmarkMutationKey = "updateBookmark"; export const useUpdateBookmarkMutation = () => { - const queryClient = useQueryClient(); + const queryClient = getQueryClient(); return useMutation({ mutationFn: (bookmark: Parameters[0]) => diff --git a/src/app/(pages)/(home)/_state/mutations/use-url-metadata-mutation.tsx b/src/app/(pages)/(home)/_state/mutations/use-url-metadata-mutation.tsx index cf2825c..231af84 100644 --- a/src/app/(pages)/(home)/_state/mutations/use-url-metadata-mutation.tsx +++ b/src/app/(pages)/(home)/_state/mutations/use-url-metadata-mutation.tsx @@ -1,10 +1,10 @@ import { useMutation } from "@tanstack/react-query"; import { metadataService } from "../../services/metadata-service"; -import { useQueryClient } from "@tanstack/react-query"; import { bookmarksQueries } from "../queries/bookmark-query"; +import { getQueryClient } from "~/app/_core/utils/get-query-client"; export const useUrlMetadataMutation = () => { - const queryClient = useQueryClient(); + const queryClient = getQueryClient(); return useMutation({ mutationFn: (url: string) => metadataService.getMetadata(url), diff --git a/src/app/(pages)/(home)/page.tsx b/src/app/(pages)/(home)/page.tsx index b291ba7..ec28df9 100644 --- a/src/app/(pages)/(home)/page.tsx +++ b/src/app/(pages)/(home)/page.tsx @@ -1,19 +1,12 @@ +import { Suspense } from "react"; import { BookmarkInput } from "./_components/bookmark-input"; import { BookmarkList } from "./_components/bookmark-list"; import { bookmarksQueries } from "./_state/queries/bookmark-query"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; +import { ServerPrefetcher } from "~/app/_common/providers/server-prefetcher"; export default async function HomePage() { - const queryClient = new QueryClient(); - - await queryClient.prefetchQuery(bookmarksQueries.bookmarks()); - return ( - +

{`Bookmarket - Buy and Sell Expert's Bookmark Collections`} @@ -21,6 +14,6 @@ export default async function HomePage() {

-
+ ); } diff --git a/src/app/(pages)/layout.tsx b/src/app/(pages)/layout.tsx index e845e8f..b3495ec 100644 --- a/src/app/(pages)/layout.tsx +++ b/src/app/(pages)/layout.tsx @@ -44,7 +44,7 @@ export const metadata: Metadata = { siteName: "BookMarket", images: [ { - url: "https://utfs.io/f/3A5RWyP8uGdp1aTyPGvFNZ8uUODoJXCrmlfzwiqaygGRY0Qv", + url: "https://utfs.io/f/xLzQ78o3fSpa5oVbiU4FX9O4zvxkP8oepgE3dacNjwsR7yTY", width: 1200, height: 1200, alt: "BookMarket - Buy and Sell Curated Bookmark Collections", diff --git a/src/app/_common/providers/global-provider.tsx b/src/app/_common/providers/global-provider.tsx index 6d0c244..9bd13d3 100644 --- a/src/app/_common/providers/global-provider.tsx +++ b/src/app/_common/providers/global-provider.tsx @@ -1,23 +1,14 @@ "use client"; import { ClerkProvider } from "@clerk/nextjs"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import React from "react"; import { useBodyScrollLock } from "../hooks/use-body-scroll-lock"; +import { getQueryClient } from "~/app/_core/utils/get-query-client"; export const GlobalProvider = ({ children }: { children: React.ReactNode }) => { - const [queryClient] = React.useState( - () => - new QueryClient({ - defaultOptions: { - queries: { - staleTime: 1000 * 5, - gcTime: 1000 * 5, - }, - }, - }), - ); + const [queryClient] = React.useState(() => getQueryClient()); useBodyScrollLock(); return ( diff --git a/src/app/_common/providers/server-prefetcher.tsx b/src/app/_common/providers/server-prefetcher.tsx new file mode 100644 index 0000000..d7bec43 --- /dev/null +++ b/src/app/_common/providers/server-prefetcher.tsx @@ -0,0 +1,25 @@ +import { + dehydrate, + HydrationBoundary, + type UseQueryOptions, +} from "@tanstack/react-query"; +import React from "react"; +import { getQueryClient } from "~/app/_core/utils/get-query-client"; + +export const ServerPrefetcher = async ({ + children, + query, +}: { + children: React.ReactNode; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + query: UseQueryOptions; +}) => { + const queryClient = getQueryClient(); + await queryClient.prefetchQuery(query); + + return ( + + {children} + + ); +}; diff --git a/src/app/_core/utils/get-query-client.ts b/src/app/_core/utils/get-query-client.ts new file mode 100644 index 0000000..ca4b22f --- /dev/null +++ b/src/app/_core/utils/get-query-client.ts @@ -0,0 +1,28 @@ +import { isServer, QueryClient } from "@tanstack/react-query"; + +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + staleTime: 60 * 1000, + refetchOnWindowFocus: false, + }, + }, + }); +} + +let browserQueryClient: QueryClient | undefined = undefined; + +export function getQueryClient() { + if (isServer) { + // Server: always make a new query client + return makeQueryClient(); + } else { + // Browser: make a new query client if we don't already have one + // This is very important, so we don't re-make a new client if React + // suspends during the initial render. This may not be needed if we + // have a suspense boundary BELOW the creation of the query client + if (!browserQueryClient) browserQueryClient = makeQueryClient(); + return browserQueryClient; + } +} diff --git a/src/server/queries/bookmark.ts b/src/server/queries/bookmark.ts index 7b683ad..9876df0 100644 --- a/src/server/queries/bookmark.ts +++ b/src/server/queries/bookmark.ts @@ -13,7 +13,7 @@ export const getBookmarks = async () => { return []; } - return await db + return db .select() .from(bookmarks) .where(eq(bookmarks.userId, userId))