😽

【TanStack Start】TanStack Start【#5 tRPC Setup】

に公開

【#5 tRPC Setup】
YouTube: https://youtube.com/live/9cGMUjBgw_U
https://youtube.com/live/9cGMUjBgw_U
https://github.com/tainakarorue/2026-tanstack-start-lesson-youtube/tree/5-trpc-setup

今回はtRPCを実装します。

npm install @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query
src/trpc/init.ts
import { initTRPC } from '@trpc/server'

const t = initTRPC.create()

export const router = t.router
export const publicProcedure = t.procedure
src/trpc/router.ts
import { router, publicProcedure } from './init'

export const appRouter = router({
  hello: publicProcedure.query(() => {
    return { message: 'Hello tRPC' }
  }),
})

export type AppRouter = typeof appRouter
src/routes/api/trpc.$.ts
import { createFileRoute } from '@tanstack/react-router'
import { fetchRequestHandler } from '@trpc/server/adapters/fetch'

import { appRouter } from '@/trpc/router'

function handleRequest(request: Request) {
  return fetchRequestHandler({
    endpoint: '/api/trpc',
    req: request,
    router: appRouter,
    createContext: () => ({}),
  })
}

export const Route = createFileRoute('/api/trpc/$')({
  server: {
    handlers: {
      GET: ({ request }) => handleRequest(request),
      POST: ({ request }) => handleRequest(request),
    },
  },
})
src/trpc/query-client.ts
import { QueryClient } from '@tanstack/react-query'

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60,
    },
  },
})
src/trpc/client.ts
import { createTRPCClient, httpBatchLink } from '@trpc/client'
import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query'

import type { AppRouter } from './router'
import { queryClient } from './query-client'

const client = createTRPCClient<AppRouter>({
  links: [
    httpBatchLink({
      url: '/api/trpc',
    }),
  ],
})

export const trpc = createTRPCOptionsProxy<AppRouter>({
  client,
  queryClient,
})
src/routes/__root.tsx
// src/routes/__root.tsx
/// <reference types="vite/client" />
import type { ReactNode } from 'react'
import {
  Outlet,
  createRootRoute,
  HeadContent,
  Scripts,
} from '@tanstack/react-router'
import { QueryClientProvider } from '@tanstack/react-query'

import { queryClient } from '@/trpc/query-client'

import '../app.css'

export const Route = createRootRoute({
  notFoundComponent: () => <p>404 - Page Not Found</p>,
  head: () => ({
    meta: [
      {
        charSet: 'utf-8',
      },
      {
        name: 'viewport',
        content: 'width=device-width, initial-scale=1',
      },
      {
        title: 'TanStack Start Starter',
      },
    ],
  }),
  component: RootComponent,
})

function RootComponent() {
  return (
    <QueryClientProvider client={queryClient}>
      <RootDocument>
        <Outlet />
      </RootDocument>
    </QueryClientProvider>
  )
}

function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
  return (
    <html>
      <head>
        <HeadContent />
      </head>
      <body>
        {children}
        <Scripts />
      </body>
    </html>
  )
}

Discussion