PavidR
PavidR3mo ago

Correct tRPC implementation (NextJS AppDir)

GitHub
examples-next-app-dir/src/trpc/server-http.ts at main · trpc/exampl...
Contribute to trpc/examples-next-app-dir development by creating an account on GitHub.
GitHub
examples-next-app-dir/src/trpc/server-invoker.ts at main · trpc/exa...
Contribute to trpc/examples-next-app-dir development by creating an account on GitHub.
GitHub
examples-next-app-dir/src/trpc/rq-server.ts at main · trpc/examples...
Contribute to trpc/examples-next-app-dir development by creating an account on GitHub.
26 Replies
Hobbs
Hobbs3mo ago
Hey @PavidR I'm in the exact same boat as you - curious if you made a decision/any progress since you posted this 12 hours ago?
PavidR
PavidR3mo ago
I went with the T3 app implementation, using the hydration helpers from react-query/rsc package But I’m still wondering how this work. I’m doing queries in RSC, but still experiencing loading times. I’ve seen no difference whatsoever between implementations Let me know what you picked !
Hobbs
Hobbs3mo ago
Awesome, thank you for sharing! I can probably help with the loading times if you want to minimize or simulate it being instantaneous. Curious - do you have to do a trpc server / client implementation? Meaning a separate procedure/instance if you want to use trpc to make requests on the server side vs client?
PavidR
PavidR3mo ago
Yes, there are 2 different way to use tRPC depending if RSC/server or client If I got your question right :kekw2:
Hobbs
Hobbs3mo ago
Yeah that's my understand I guess just figuring out which pattern to use is the tricky part
PavidR
PavidR3mo ago
for RSC/server there are 3 different ways ...That's...Confusing, not to say the least
Hobbs
Hobbs3mo ago
What's confusing to me is in the pages router you'd have a withTRPC that wraps the app router / App itself In app directory from what I understand is we create that kind of psuedo provider and combine it with a query provider to wrap the application and both of those use local state for the queryClient/trpcClient
PavidR
PavidR3mo ago
yeah that's it I've never looked into the withTRPC hoc code
Hobbs
Hobbs3mo ago
So i'm basically importing my trpc from /utils/trpc.ts then using that to make my requests however I have no clue how you would differentiate this from a server vs client (i'm using the createTRPCNext method , does this handle if it's client vs server on it's own or did you by any chance go down the rabbit hole of setting up a createCallerFactory? haha I haven't even gone down the ssr/ssg options yet. I have requests working I just feel it's pretty verbose on distinguishing which caller to use depending on server/client
PavidR
PavidR3mo ago
Honestly all of this is so not documented that, you should trust maintainers implementations, like in T3 and be as flexible as possible in case of API changes
Hobbs
Hobbs3mo ago
agreed yup
PavidR
PavidR3mo ago
honestly, 50% of the time I feel bad to use TRPC
Hobbs
Hobbs3mo ago
Are you familiar with react query?
PavidR
PavidR3mo ago
because I don't understand half of it I get the broad picture, but not the fine details
Hobbs
Hobbs3mo ago
For the loading times it sounds like it has to do with your refetchInterval/staleTime If you are using the hydration pattern you can preFetch/PreHydrate your data as well and that can make it appear quicker
PavidR
PavidR3mo ago
I think yeah, that's what I've to do but its not really documented
Hobbs
Hobbs3mo ago
I can help you out with that stuff if you want to have more granularity on when you are fetching/populating Yeah I really recommend the ui.dev react query course, its a little expensive but it helped me out heaps
PavidR
PavidR3mo ago
I display a list of questions, when clicking the question I'm redirected to a page where I display the single question and the loading happens the
app/questions/[id]/page.tsx
app/questions/[id]/page.tsx
is doing the RSC tRPC call and I pass down the initialData to my <Question /> component and inside the Question component, I use the tRPC CLIENT stuff, passing initialData from props so when I'm doing mutations etc, I benefit of the ReactQuery stuff, like optimistic UI etc
Hobbs
Hobbs3mo ago
Yeah that sounds like a good pattern to use. Maybe think about if you want the fetch to occur on the parent level and then render the component conditionally or if you want to render the component Another thing to note is that if you are using server actions that those can't run in parallel (you might want to double check to confirm) but I recall that being the case. So basically I try to stick to using server actions only for mutations also keep in mind that RSC are different than a server action
PavidR
PavidR3mo ago
nah I don't use server actions because I need every part of my API to be usable on a React Native app, later on 👍
Hobbs
Hobbs3mo ago
oh great then hmm, im not sure why the load times would be exagerated with trpc
PavidR
PavidR3mo ago
and I don't want to maintain : an API + bunch of server actions that do the same thing
Hobbs
Hobbs3mo ago
if anything you should see some optimizations what with the batching/deduping and stuff that rq has out of the box for trpc to leverage
PavidR
PavidR3mo ago
I mean, maybe the little loading times are normal/OK is there a way to see the timeline of a RSC ? from call to render, times etc ?
Hobbs
Hobbs3mo ago
This has been a big trip for me, its too easy for duplicate actions to exist. It's too easy to fall into the pattern of creating a hook, to make a trpc call, to use a server action Yup do you have the tanstack devtools installed? If your layout/provider looks like this, you can add it in like so:
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
{children}
</QueryClientProvider>
</trpc.Provider>
);
return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
{children}
</QueryClientProvider>
</trpc.Provider>
);
PavidR
PavidR3mo ago
Yeah OK thanks, but that doesn't exist for RSC but its late here in EU, gonna sleep and see this tomorrow ! thanks have a good one well @Hobbs I opted for prefetching in server components and leveraging useSuspenseQuery hook in client components + HydrateClient does wonders, for now