All Articles

Can NextJS Be A tRPC Client?

Jack Herrington
Jack Herrington
August 20th, 2023

Question: Can my NextJS routes and components call tRPC endpoints on the server with the App Router?

Answer: NextJS applications running on the App Router can definitely call RPC endpoints on the same NextJS server, or any tRPC deployed microservice.

Let's start with getting some libraries installed:


pnpm add @trpc/client @trpc/react-query @tanstack/react-query

Next we need to create a tRPC client object. That's going to have all the good stuff like the hooks we will use later on the client to do the queries and mutations.


import { createTRPCReact } from "@trpc/react-query";
import { type AppRouter } from "@/server";
export const trpc = createTRPCReact<AppRouter>({});

You can put this file wherever you want in your app directory (or outside it). I put it in app/_trpc/client.ts. You'll also need to alter the @/server important to point to wherever the AppRouter types are for your target endpoint.

Once we have our tRPC client ready to go we need to create the React providers that will provide both the tRPC client and the react-query client down the tree.


"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
import React, { useState } from "react";
import { trpc } from "./client";
export default function Provider({ children }: { children: React.ReactNode }) {
const [queryClient] = useState(() => new QueryClient({}));
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
url: "http://localhost:3000/api/trpc",
}),
],
})
);
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
);
}

This is a "client" component becuase it uses context and hooks. The useState hooks are used to store the instances of the React-Query and trpc clients, which are then sent to any children components using the providers.

I put this file in app/_trpc/Provider.tsx but again, you can put this component wherever you want.

Once we have the provider we need to put them into the root layout so they are available on any route. To do that simply import the Provider component:


import Provider from "@/app/_trpc/Provider";

And then wrap the children in the layout with the Provider:


return (
<html lang="en">
<body className={inter.className}>
<Provider>{children}</Provider>
</body>
</html>
);

Now we are ready to make query or mutation requests in any client component we want. We simply grab the hook:


const getTodos = trpc.getTodos.useQuery();

And then the data from the query will come in on getTodos.data.

Making requests from React Server Components requires a different client. I put mine in /app/_trpc/serverClient.tsx:


import { httpBatchLink } from "@trpc/client";
import { appRouter } from "@/server";
export const serverClient = appRouter.createCaller({
links: [
httpBatchLink({
url: "http://localhost:3000/api/trpc",
}),
],
});

On the server we are going to be making HTTP requests directly using fetch, there is no need for providers. So we create a caller by point the createCaller method at our endpoint location.

Then in our RSC we import the client and make the call.


import TodoList from "./_components/TodoList";
import { serverClient } from "./_trpc/serverClient";
export default async function Home() {
const todos = await serverClient.getTodos();
return ...
}

In this case todos variable will be the data coming back from the endpoint. Then we can render that data right in the RSC, or pass it down to any client components as a property to seed their initial state.

Share this article with your friends

Subscribe for Free Tips, Tutorials, and Special Discounts

We're in this together!

We respect your privacy. Unsubscribe at any time.

Jack Herrington

Written by Jack Herrington

Jack Herrington is a Full Stack Principal Engineer who orchestrated the rollout of React/NextJS at Walmart Labs and Nike. He is also the "Blue Collar Coder" on YouTube where he posts weekly videos on advanced use of React and NextJS as well as other frontend technologies trends. His YouTube channel hosts an entire free courses on React and TypeScript. He has written seven books including most recently No-BS TypeScript which is a companion book to the YouTube course.