From 29b7c5c8d10d5315fea27fc25f1f153c6c12dfbf Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sat, 2 Mar 2024 20:45:11 +0000 Subject: [PATCH] fix: Fix hydration in list view caused by the spinner --- .../bookmarks/components/BookmarksGrid.tsx | 13 ++++---- .../web/app/dashboard/components/AllLists.tsx | 12 +++++--- .../lists/components/AllListsView.tsx | 8 ++--- packages/web/lib/providers.tsx | 30 ++++++++++++++++++- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx index 293b7765..554d20a0 100644 --- a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx +++ b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx @@ -5,15 +5,15 @@ import { ZBookmark, ZGetBookmarksRequest } from "@/lib/types/api/bookmarks"; import { api } from "@/lib/trpc"; import TextCard from "./TextCard"; import { Slot } from "@radix-ui/react-slot"; -import Masonry from 'react-masonry-css'; -import resolveConfig from 'tailwindcss/resolveConfig' -import tailwindConfig from '@/tailwind.config' +import Masonry from "react-masonry-css"; +import resolveConfig from "tailwindcss/resolveConfig"; +import tailwindConfig from "@/tailwind.config"; import { useMemo } from "react"; function getBreakpointConfig() { - const fullConfig = resolveConfig(tailwindConfig) + const fullConfig = resolveConfig(tailwindConfig); - const breakpointColumnsObj: {[key: number]: number, default: number} = { + const breakpointColumnsObj: { [key: number]: number; default: number } = { default: 3, }; breakpointColumnsObj[parseInt(fullConfig.theme.screens.lg)] = 2; @@ -22,7 +22,6 @@ function getBreakpointConfig() { return breakpointColumnsObj; } - function renderBookmark(bookmark: ZBookmark) { let comp; switch (bookmark.content.type) { @@ -58,7 +57,7 @@ export default function BookmarksGrid({ return

No bookmarks

; } return ( - + {data.bookmarks.map((b) => renderBookmark(b))} ); diff --git a/packages/web/app/dashboard/components/AllLists.tsx b/packages/web/app/dashboard/components/AllLists.tsx index c8b55d73..8903c82a 100644 --- a/packages/web/app/dashboard/components/AllLists.tsx +++ b/packages/web/app/dashboard/components/AllLists.tsx @@ -2,17 +2,21 @@ import { api } from "@/lib/trpc"; import SidebarItem from "./SidebarItem"; -import LoadingSpinner from "@/components/ui/spinner"; import NewListModal, { useNewListModal } from "./NewListModal"; import { Plus } from "lucide-react"; import Link from "next/link"; import { ZBookmarkList } from "@/lib/types/api/lists"; -export default function AllLists({initialData}: {initialData: {lists: ZBookmarkList[]}}) { - const { data: lists } = api.lists.list.useQuery(undefined, { +export default function AllLists({ + initialData, +}: { + initialData: { lists: ZBookmarkList[] }; +}) { + let { data: lists } = api.lists.list.useQuery(undefined, { initialData, }); - + // TODO: This seems to be a bug in react query + lists ||= initialData; const { setOpen } = useNewListModal(); return ( diff --git a/packages/web/app/dashboard/lists/components/AllListsView.tsx b/packages/web/app/dashboard/lists/components/AllListsView.tsx index 155cdbcf..d81f5fca 100644 --- a/packages/web/app/dashboard/lists/components/AllListsView.tsx +++ b/packages/web/app/dashboard/lists/components/AllListsView.tsx @@ -1,7 +1,6 @@ "use client"; import { Button } from "@/components/ui/button"; -import LoadingSpinner from "@/components/ui/spinner"; import { api } from "@/lib/trpc"; import { ZBookmarkList } from "@/lib/types/api/lists"; import { keepPreviousData } from "@tanstack/react-query"; @@ -35,14 +34,13 @@ export default function AllListsView({ initialData: ZBookmarkList[]; }) { const { setOpen: setIsNewListModalOpen } = useNewListModal(); - const { data: lists } = api.lists.list.useQuery(undefined, { + let { data: lists } = api.lists.list.useQuery(undefined, { initialData: { lists: initialData }, placeholderData: keepPreviousData, }); - if (!lists) { - return ; - } + // TODO: This seems to be a bug in react query + lists ||= { lists: initialData }; return (
diff --git a/packages/web/lib/providers.tsx b/packages/web/lib/providers.tsx index 0c721c1e..5c4649b5 100644 --- a/packages/web/lib/providers.tsx +++ b/packages/web/lib/providers.tsx @@ -9,6 +9,34 @@ import superjson from "superjson"; import { SessionProvider } from "next-auth/react"; import { Session } from "next-auth"; +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + // With SSR, we usually want to set some default staleTime + // above 0 to avoid refetching immediately on the client + staleTime: 60 * 1000, + }, + }, + }); +} + +let browserQueryClient: QueryClient | undefined = undefined; + +function getQueryClient() { + if (typeof window === "undefined") { + // 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 + // supsends 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; + } +} + export default function Providers({ children, session, @@ -16,7 +44,7 @@ export default function Providers({ children: React.ReactNode; session: Session | null; }) { - const [queryClient] = React.useState(() => new QueryClient()); + const queryClient = getQueryClient(); const [trpcClient] = useState(() => api.createClient({