Introduktion till tRPC
Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →
tRPC ger dig typsäkerhet från server till klient (hela vägen), utan att ens behöva deklarera typer. På serversidan returnerar du bara data i en funktion, och på klientsidan använder du datan direkt baserat på endpoint-namnet.
👋 Jag är Alex, eller "KATT" på GitHub, och jag vill berätta om ett bibliotek som heter tRPC. Jag har inte publicerat några artiklar om det ännu, så jag skriver bara den här introduktionen för att sätta igång (men vi har redan nått >530 🌟 på GitHub). Räkna med artiklar och videointroduktioner framöver! Om du vill hålla dig uppdaterad eller ställa frågor kan du följa mig på Twitter @alexdotjs.
Så här kan det se ut när du gör ett tRPC-anrop från klienten till en endpoint:

Jag har skapat ett bibliotek för React (@trpc/react) som bygger på det fantastiska react-query, men klientbiblioteket (@trpc/client) fungerar utan React (om du vill bygga ett bibliotek för Svelte/Vue/Angular/[..] - hör av dig!)
Ingen kodgenerering krävs och du kan enkelt lägga till det i ditt befintliga Next.js/CRA/Express-projekt.
Exempel
Här är ett exempel på en tRPC-procedur (kallas även endpoint) som heter hello och tar ett string-argument.
tsxconst appRouter = trpc.router().query('hello', {input: z.string().optional(),resolve: ({ input }) => {return {text: `hello ${input ?? 'world'}`,};},});export type AppRouter = typeof appRouter;
tsxconst appRouter = trpc.router().query('hello', {input: z.string().optional(),resolve: ({ input }) => {return {text: `hello ${input ?? 'world'}`,};},});export type AppRouter = typeof appRouter;
Och här är en typsäker klient som använder datan:
tsximport type { AppRouter } from './server';async function main() {const client = createTRPCClient<AppRouter>({url: `http://localhost:2022`,});const result = await client.query('hello', '@alexdotjs');console.log(result); // --> { text: "hello @alexdotjs" }}main();
tsximport type { AppRouter } from './server';async function main() {const client = createTRPCClient<AppRouter>({url: `http://localhost:2022`,});const result = await client.query('hello', '@alexdotjs');console.log(result); // --> { text: "hello @alexdotjs" }}main();
Det är allt du behöver för typsäkerhet! result härleds automatiskt från vad servern returnerar. Indata härleds också från validerarens returvärde, så datan är säker att använda direkt – faktiskt måste du alltid skicka indata genom en validerare (tRPC fungerar out-of-the-box med zod/yup/egna validerare).
Här är en CodeSandbox-länk där du kan testa exemplet ovan: https://githubbox.com/trpc/trpc/tree/main/examples/standalone-server (titta på terminalutmatningen istället för förhandsgranskningen!)
Va? Importerar jag kod från min server till klienten? - Nej, det gör du faktiskt inte
Även om det kan se ut så, delas ingen kod från server till klient; TypeScripts import type "[...] importerar endast deklarationer för typannoteringar. Den tas alltid bort helt och hållet och lämnar inga spår vid körning." – en funktion tillagd i TypeScript 3.8 - läs i TypeScript-dokumentationen.
Ingen kodgenerering är inblandad – du kan implementera detta direkt i din applikation om du har ett sätt att dela typer mellan server och klient (förhoppningsvis använder du redan en monorepo).
Men vi har precis börjat!
Jag nämnde tidigare att det finns ett React-bibliotek. Så här använder du datan i React:
tsxconst { data } = trpc.useQuery(['hello', '@alexdotjs']);
tsxconst { data } = trpc.useQuery(['hello', '@alexdotjs']);
...och du får typsäker data på klienten.
Du kan implementera tRPC redan idag i ditt befintliga projekt (det finns adaptrar för Express/Next.js). Det fungerar utmärkt med CRA och bör fungera med React Native också. Det är inte ens knutet till React – om du vill skapa ett bibliotek för Svelte eller Vue, kontakta mig.
Hur hanterar man datamutationer?
Mutationer är lika enkla som queries – de är faktiskt samma sak under huven, men exponeras som syntaktisk socker och genererar HTTP POST-förfrågningar istället för GET.
Här är ett lite mer komplext exempel med en databas, hämtat från vårt TodoMVC-exempel på todomvc.trpc.io / https://github.com/trpc/trpc/tree/main/examples/next-prisma-todomvc
tsxconst todoRouter = createRouter().mutation('add', {input: z.object({id: z.string().uuid(),data: z.object({completed: z.boolean().optional(),text: z.string().min(1).optional(),}),}),async resolve({ ctx, input }) {const { id, data } = input;const todo = await ctx.task.update({where: { id },data,});return todo;},});
tsxconst todoRouter = createRouter().mutation('add', {input: z.object({id: z.string().uuid(),data: z.object({completed: z.boolean().optional(),text: z.string().min(1).optional(),}),}),async resolve({ ctx, input }) {const { id, data } = input;const todo = await ctx.task.update({where: { id },data,});return todo;},});
Och användningen med React ser ut så här:
tsxconst addTask = trpc.useMutation('todos.add');return (<><inputplaceholder="What needs to be done?"onKeyDown={(e) => {const text = e.currentTarget.value.trim();if (e.key === 'Enter' && text) {addTask.mutate({ text });e.currentTarget.value = '';}}}/></>)
tsxconst addTask = trpc.useMutation('todos.add');return (<><inputplaceholder="What needs to be done?"onKeyDown={(e) => {const text = e.currentTarget.value.trim();if (e.key === 'Enter' && text) {addTask.mutate({ text });e.currentTarget.value = '';}}}/></>)
Slut, för nu.
Slut, för tillfället.
-
Skapa kontext för inkommande förfrågningar för användarspecifik data som injiceras som beroende i resolver-funktionerna - länk
-
Stöd för middleware i routrar - länk
-
Slå samman routrar (du vill förmodligen inte ha all din backenddata i en fil) - länk
-
Enklaste server-side rendering du någonsin sett i React med vår
@trpc/next-adapter - länk -
Typsäker felformatering - länk
-
Datatransformatorer (använd Date/Map/Set-objekt över nätet) - länk
-
Hjälpfunktioner för React Query
Om du vill komma igång finns det några exempel i Komma igång med Next.js.
