reed
reed
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
Good shout. I hadn't thought of that
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
That repo demos a mutation example. The newer way: https://github.com/t3-oss/create-t3-turbo/blob/main/apps/nextjs/src/app/_components/posts.tsx#L37
const createPost = useMutation(
trpc.post.create.mutationOptions({
onSuccess: async () => {
form.reset();
await queryClient.invalidateQueries(trpc.post.pathFilter());
},
onError: (err) => {
toast.error(
err.data?.code === "UNAUTHORIZED"
? "You must be logged in to post"
: "Failed to create post",
);
},
}),
);
const createPost = useMutation(
trpc.post.create.mutationOptions({
onSuccess: async () => {
form.reset();
await queryClient.invalidateQueries(trpc.post.pathFilter());
},
onError: (err) => {
toast.error(
err.data?.code === "UNAUTHORIZED"
? "You must be logged in to post"
: "Failed to create post",
);
},
}),
);
Whereas the older way might have been trpc.post.create.useMutation()
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
I don't envy you. Good luck. That create-t3-turbo app is a great reference, but it's worth noting that they are now showcasing a newer way to integrate tRPC with TanstackQuery. I believe the goal is to decouple the two libraries more explicitly, which I'm a fan of. But historically (so you might see lots of examples of this when Googling) the client-side tRPC router client had a more direct integration, so that I would have historically done something like api.posts.all.useQuery() when data fetching on the client.
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
I'm sure migration is a pain. Luckily I haven't had to do that. But aside from the SSR+auth issue that I linked above, devx and more importantly UX is way better imo.
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
Well, sure. I think there they're talking about what I've been calling the server-side tRPC router client. That has no direct integration with TanstackQuery. So you still need to wire it into the Hydration
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
Hmm interesting! I'll have to look into fetchQuery
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
I don't fully understand everything here, but my loose conception is that in App router SSR with TanstackQuery, a common approach is to fetch the data fully on the server and use that as the initial data on the client-side TanstackQuery, but it's presumably tagged as prefetch/SSR so that it also then hydrates on the client. So there is complete initial data, but it uses the TanstackQuery caching rules that you configure to know when to re-fetch that data on the client. I'm definitely glossing over some of the specifics here. Maybe for prefetch/SSR it always refetches on the client once it loads. I'm not totally sure.
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
In server.tsx they're creating the HydrateClient component to facilitate the SSR handoff to TanstackQuery on the client
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
I'll use the create-t3-turbo repo as example since I think it's pretty up-to-date. This directory: https://github.com/t3-oss/create-t3-turbo/tree/main/apps/nextjs/src/trpc Has the query-client.ts file (tanstack query) Then a react.tsx file for the client-side tRPC router client And a server.tsx file for the server-side tRPC router client. I think that will show you how and where TanstackQuery (formerly React Query) can integrate into tRPC
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
The last thing I'll mention is that the tRPC setup that I've used and seen often includes a server-side router (does not use tanstack query), so that you can use your same tRPC router client on the server internally. So for server-side data fetching, I would use that tRPC router client. I think create-t3-turbo has an example of that as well
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
Your saying "App router" has made me assume you're using Next.js. "Tanstack" is now a little ambiguous. TanstackStart instead of Nextjs? Or TanstackQuery for client-side async state management?
50 replies
TtRPC
Created by spreen_co on 4/1/2025 in #❓-help
Migrating pages router to app router
I don't have time to go super deep into this right now, but I can help clear up some of the easier-to-solve issues. First, searchParams and params. As you noted, there are hooks that you can use to get these pieces on the client, but in a server component page, you can also get these directly as props. For example, params: https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#example (This examples assumes latest version of Nextjs.) searchParams prop works the same way. So if you want/need it, this gives you a way to get that data on a server component, and use it for DB calls or whatever, and then send data (or unresolved promises) to client components. For SSR, you can use a HydrateClient component from tRPC setup in your server component to facilitate the server->client data flow. Here is an example in create-t3-turbo repo: https://github.com/t3-oss/create-t3-turbo/blob/main/apps/nextjs/src/app/page.tsx That works great for public data, but if the data fetching requires auth, there is an open issue with SSR in Nextjs (I'm assuming it's still open): https://github.com/vercel/next.js/discussions/60640 Personally I've taken the quick route and removed SSR for private data, but I plan to revisit this eventually.
50 replies
TtRPC
Created by tyler4949 on 3/9/2025 in #❓-help
Creating Service Layer in Next App Router
Also, at the risk of overexplaining stuff lol, I'll say that I've also found it useful to create a layer on the server that controls my database IO, integrations with external APIs, etc. And my tRPC router procedures call these functions. That way I keep my tRPC code focused on communication over the network, and a consistent, composable router API. The create-t3-turbo is simple because it's an example, but in a "real" codebase this code
create: protectedProcedure
.input(CreatePostSchema)
.mutation(({ ctx, input }) => {
return ctx.db.insert(Post).values(input);
}),
create: protectedProcedure
.input(CreatePostSchema)
.mutation(({ ctx, input }) => {
return ctx.db.insert(Post).values(input);
}),
Would look something like this instead
create: protectedProcedure
.input(CreatePostSchema)
.mutation(createPost),
create: protectedProcedure
.input(CreatePostSchema)
.mutation(createPost),
And this hypothetical createPost function would come from a layer that creates my server-side functionality. That keeps tRPC feeling like a thin communication+API layer to me.
11 replies
TtRPC
Created by tyler4949 on 3/9/2025 in #❓-help
Creating Service Layer in Next App Router
In my opinion, the main point of RPC is to call the procedures from environment A and have them execute in environment B, e.g. calling tRPC on the client and having it execute on the server. The server-side tRPC client is more of a nice-to-have so that you can use the same code, logic, router procedures on the server that you already built for the client.
11 replies
TtRPC
Created by tyler4949 on 3/9/2025 in #❓-help
Creating Service Layer in Next App Router
I don't have any public repos I can share, sorry. But I'm happy to chat through some examples here. This create-t3-turbo repo has a tRPC setup example. Because the example repo is using Turborepo the pieces are spread across the repo a bit more. Here they have a blog post router: https://github.com/t3-oss/create-t3-turbo/blob/main/packages/api/src/router/post.ts The difference procedures here are performing database IO. Here they're using tRPC on the server to fetch all of the posts for the homepage before sending the initial HTML to the client: https://github.com/t3-oss/create-t3-turbo/blob/main/apps/nextjs/src/app/page.tsx Here they're using the post.create procedure in the client when the user creates a new post: https://github.com/t3-oss/create-t3-turbo/blob/main/apps/nextjs/src/app/_components/posts.tsx#L37 That's actually using new syntax. I know the tRPC team has been proposing new ways to wire into React Query, so I'll need to look into this example a bit more. The way that I've historically done it is via a tRPC instance that wires directly into a React Query provider, and then I would have used it like
const createPost = trpc.post.create.useMutation()
const createPost = trpc.post.create.useMutation()
I will say that on big projects I've found it convenient to create some kind of react-query layer in my front-end code that calls the tRPC integration pieces, but has control over the react-query integration so that I can be consistent about which mutations invalidate which pieces of the react-query cache, and things like that.
function useCreatePost(args) {
return api.post.create.useMutation(args);
}
function useCreatePost(args) {
return api.post.create.useMutation(args);
}
That strategy would give you that extra layer of functions between tRPC and your client component.
11 replies
TtRPC
Created by tyler4949 on 3/9/2025 in #❓-help
Creating Service Layer in Next App Router
The way I've done it is to have some set of server-side functions that the client and/or server want to use, typically for data IO. I wire those server-side IO functions into tRPC router procedures. Then when I want to use a tRPC router procedure: * Client-side use the tRPC router that wires into React Query, and passes data via the HTTP route handler function (e.g. app/api/trpc). * Server-side use server tRPC instance and call it directly, like to get initial data to use in a server component (often in an app router page.ts). So maybe what solves your problem is taking advantage of calling the same tRPC router and procedures on both client and server.
11 replies