'use client'; // ^-- to make sure we can mount the Provider from a server component import { useState } from 'react'; import type { QueryClient } from '@tanstack/react-query'; import { QueryClientProvider } from '@tanstack/react-query'; import { createTRPCClient, httpBatchLink } from '@trpc/client'; import { createTRPCContext } from '@trpc/tanstack-react-query'; import superjson from 'superjson'; import { makeQueryClient } from './query-client'; import type { AppRouter } from './routers/_app'; export const { TRPCProvider, useTRPC } = createTRPCContext(); let browserQueryClient: QueryClient; function getQueryClient() { if (typeof window === 'undefined') { // Server: always make a new query client return makeQueryClient(); } // 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; } function getUrl() { const base = (() => { if (typeof window !== 'undefined') return ''; return process.env.NEXT_PUBLIC_APP_URL; })(); return `${base}/api/trpc`; } export function TRPCReactProvider( props: Readonly<{ children: React.ReactNode; }> ) { // 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(() => createTRPCClient({ links: [ httpBatchLink({ transformer: superjson, url: getUrl(), }), ], }) ); return ( {props.children} ); }