"use client"; import React, { useState } from "react"; import superjson from "superjson"; import { httpBatchLink } from "@trpc/client"; import { createTRPCReact } from "@trpc/react-query"; import { getCurrentUrl } from "@/lib/current-url"; import { makeQueryClient } from "./query-client"; import { QueryClientProvider, type QueryClient } from "@tanstack/react-query"; import type { appRouter } from "./routers/_app"; export const trpc = createTRPCReact(); let clientQueryClientSingleton: QueryClient; function getQueryClient(): QueryClient { if (typeof window === "undefined") { // Server: always make a new query client return makeQueryClient(); } // Browser: use singleton pattern to keep the same query client return (clientQueryClientSingleton ??= makeQueryClient()); } function getUrl(): string { const base = ((): string => { if (typeof window !== "undefined") return ""; return getCurrentUrl(); })(); return `${base}/api/trpc`; } export function TRPCProvider( props: Readonly<{ children: React.ReactNode; }> ): React.JSX.Element { // NOTE: Avoid useState when initializing the query client if you don't // have a suspense boundary between this and the code that may // suspend because React will throw away the client on the initial // render if it suspends and there is no boundary const queryClient = getQueryClient(); const [trpcClient] = useState(() => trpc.createClient({ links: [ httpBatchLink({ transformer: superjson, url: getUrl(), }), ] }) ); return ( {props.children} ); }