tRPC error in a server component
Answered
Cimarrón Uruguayo posted this in #help-forum
Cimarrón UruguayoOP
const ThankYouPage: React.FC<PageProps> = async ({ searchParams }) => {
const orderId = parseInt(searchParams["orderId"] as string)
const { user } = await getServerSideUser(cookies())
declare const orders: Order[]
const [order] = orders
if (!order) return notFound()
const customerId = typeof order.user === "number" ? order.user : order.user.id
if (customerId !== user?.id) {
return redirect(`/sign-in?origin=thank-you`)
}
try {
const { data, isError, isLoading } = trpc.assets.getAssetsZip.useQuery({ orderId })
console.log(data)
} catch (error) {
console.log(error)
}
return <Component />
}117 Replies
Cimarrón UruguayoOP
@Ray you can't use react-query in a server component
Cimarrón UruguayoOP
urgh so how can i get around this?
If i convert into a client component,
then I can't get the cookies from next/headers
that's only possible in server components
check out create-t3-app
it create server caller for you
@Ray check out create-t3-app
Cimarrón UruguayoOP
what exactly should I look at?
?
is this what I'm looking for?
init an app with it or check out this
https://trpc.io/docs/server/server-side-calls
https://trpc.io/docs/server/server-side-calls
Cimarrón UruguayoOP
ok thanks!
@Ray yes
Cimarrón UruguayoOP
im having trouble with this
@Ray init an app with it or check out this
https://trpc.io/docs/server/server-side-calls
Cimarrón UruguayoOP
the docs ask me to create a caller, but this is how i've created my trpc related files:
// index.ts
import { assetsRouter } from "./assets-router";
import { authRouter } from "./auth-router";
import { paymentRouter } from "./payment-router";
import { productRouter } from "./products-router";
import { router } from "./server";
export const appRouter = router({
auth: authRouter,
products: productRouter,
payment: paymentRouter,
assets: assetsRouter
})
export type AppRouter = typeof appRouter
// server.ts
import { ExpressContext } from "@/server";
import { TRPCError, initTRPC } from "@trpc/server";
import type { PayloadRequest } from "payload/types";
import type { User } from "@/payload-types";
export const t = initTRPC.context<ExpressContext>().create()
export const router = t.router
export const publicProcedure = t.procedure
const isAuth = t.middleware(async ({ ctx, next }) => {
//
})
export const privateProcedure = t.procedure.use(isAuth)
// client.ts
import { createTRPCReact } from "@trpc/react-query"
import type { AppRouter } from "."
export const trpc = createTRPCReact<AppRouter>()I would create a caller in my server.ts file right?
@Cimarrón Uruguayo I would create a caller in my server.ts file right?
yes you could create it wherever you like
@Ray yes you could create it wherever you like
Cimarrón UruguayoOP
yep so this is the issue I get
I don't have access to the request and response (express) objects when I want to create the caller
is there a way to receive this "context" in my server component?
bruh 💀
you should use
t.createCallerFactory(appRouter).createCaller() I thinkCimarrón UruguayoOP
yeah I saw that
createCallerFactory is not a valid methodhave you create a project with
create-t3-app?Cimarrón UruguayoOP
it should have what you need
Cimarrón UruguayoOP
i don't want to use create-t3-app though
i have created a sample t3-app elsewhere and the createCallerFactory method does show up now
@Cimarrón Uruguayo i don't want to use create-t3-app though
I mean check their template how they create the caller
Cimarrón UruguayoOP
ah yeah
ill learn this another time
tRPC wasn't my focus
I appreciate your help though, I'll keep this noted for the future
Basset Artésien Normand
Hi @Cimarrón Uruguayo I guess you were not using the NextJS server? Did you have a separate backend / server? and did you get it working now ?
Also @Ray Will the suggestions above work when using a separate backend / server ? ( but still within a monorepo )
@Basset Artésien Normand Hi <@473221703418511360> I guess you were not using the NextJS server? Did you have a separate backend / server? and did you get it working now ?
Cimarrón UruguayoOP
I am using a nextjs server, just that it was created manually withing express
as for getting it working, it started working out of nowhere
Basset Artésien Normand
So you are using a custom server within nextJS ?
Cimarrón UruguayoOP
it is still nextjs
just that I construct the nextjs server manually
Basset Artésien Normand
Hm, seems the server side calls are for when you need to call the procedures from the same server they are hosted in.
You may need to call your procedure(s) directly from the same server they're hosted in, createCallerFactory() can be used to achieve this. This is useful for server-side calls and for integration testing of your tRPC procedures. That is at least in regards to the server side calls documentationCimarrón UruguayoOP
in a server.ts file, instead of running like
next dev@Basset Artésien Normand Hm, seems the server side calls are for when you need to call the procedures from the same server they are hosted in.
`You may need to call your procedure(s) directly from the same server they're hosted in, createCallerFactory() can be used to achieve this. This is useful for server-side calls and for integration testing of your tRPC procedures.` That is at least in regards to the server side calls documentation
Cimarrón UruguayoOP
yeah i'm pretty sure this would be the solution
client side errored out 🤷â€â™‚ï¸
Basset Artésien Normand
But in my case i have a monorepo, but the client and server will be deployed separately
Cimarrón UruguayoOP
how is that possible
nextjs sort of blurs the separation between client and server
Basset Artésien Normand
exactly and i am really struggling to find a good example for what i want to do
mostly because of nextJS v14 and app router
Basset Artésien Normand
I still can't understand how this works. @Ray Are you available to help at all
Basset Artésien Normand
My Setup:
Monorepo
Apps:
api - fastify server with tRPC
web - NextJS v14.0.4 - App Router
These 2 apps will be deployed separately. The Server-side calls you mentioned seem to be aimed at when the application is deployed as a single unit.
I've also looked at: https://trpc.io/docs/v11/client/nextjs/server-side-helpers but the documentations seem to be aimed at the file system router.
I want to be able to make tRPC calls both on the client AND when server side rendering the page.
Monorepo
Apps:
api - fastify server with tRPC
web - NextJS v14.0.4 - App Router
These 2 apps will be deployed separately. The Server-side calls you mentioned seem to be aimed at when the application is deployed as a single unit.
I've also looked at: https://trpc.io/docs/v11/client/nextjs/server-side-helpers but the documentations seem to be aimed at the file system router.
I want to be able to make tRPC calls both on the client AND when server side rendering the page.
@Ray check out create-t3-app
have you check out this?
Basset Artésien Normand
yes ive looked at that a lot. and its something that utilises the NextJS server and when the application will be deployed as a single unit.
I would create a trpc package and import it from api and web
Basset Artésien Normand
I don't understand
I'll still need to interface with the tRPC server using HTTP requests
@Basset Artésien Normand I'll still need to interface with the tRPC server using HTTP requests
what do you need to interface?
Basset Artésien Normand
i mean. communicate
for
api?are you using turbo repo?
Basset Artésien Normand
Ill need to be able to communicate between trpc client and trpc server using http requests, as trpc will be hosted in a separate location
@Ray are you using turbo repo?
Basset Artésien Normand
no, pnpm workspaces
create a new package and export the trpc router
then you can install it on
api and webBasset Artésien Normand
i can access the
appRouter from webyou cant access the appRouter from api?
Basset Artésien Normand
the
appRouter is within the apiappso you have access to appRouter in api and web?
well, you should create another package for it
Monorepo
Apps:
api - fastify server with tRPC
web - NextJS v14.0.4 - App Router
trpc
Apps:
api - fastify server with tRPC
web - NextJS v14.0.4 - App Router
trpc
Basset Artésien Normand
Ok but how should i setup tRPC within
webyou install the trpc package in web and api
Basset Artésien Normand
and then ?
createTRPCReact, or createTRPCNext ?
@Ray you install the trpc package in web and api
Basset Artésien Normand
Do you have an example to hand?
Basset Artésien Normand
thats great thanks
Is it necessary to have tRPC in its own package?
@Basset Artésien Normand Is it necessary to have tRPC in its own package?
yes so you can install it from other app
Basset Artésien Normand
looking in here:
apps/nextjs/src/app/api/trpc/edge/[trpc]/route.ts from that repo - It doesn't look like the api endpoint exists elsewhere as its only passing the pathBasset Artésien Normand
hm wait there is also
apps/nextjs/src/trpc/server.tsthat's the caller for server component
Basset Artésien Normand
man its a little confusing
i appreciate your help by the way
I think you should init a project with
create-t3-app and play with it firstBasset Artésien Normand
yeah ive had a look at that a lot
its just it does not really apply. as its meant to be deployed as a single unit
i see your point though
@Basset Artésien Normand yeah ive had a look at that a lot
have you ever used trpc?
@Ray have you ever used trpc?
Basset Artésien Normand
no this is my first time
but the create-t3-app does it all for you. I wanted to set it all up from scratch myself to learn
why would one use route handlers?
@Basset Artésien Normand no this is my first time
if you are doing server side fetching on nextjs, you don't need to create the
route.ts which is for client side fetching@Basset Artésien Normand why would one use route handlers?
because most of work can be done with server action
Basset Artésien Normand
great thanks
does it work to simply replace
endpoint: '/api/trpc', with endpoint: 'https://<server_location>/api/trpc' if its the separate server like in my caseBasset Artésien Normand
i am going to have a search function which will fetch results from a remote 3rd party api
unless its possible to do the fetch and render server side?
Basset Artésien Normand
oh right. will that not appear slow?
How does that work exactly
How does that work exactly
Basset Artésien Normand
Hi @Ray Thanks for the great help yesterday.
Any advice regarding forwarding the headers when SSR ?
i can see in my client side request that the headers / cookies are sent. But when logging
Furthermore
my server.ts for trpc looks like this:
Any advice regarding forwarding the headers when SSR ?
i can see in my client side request that the headers / cookies are sent. But when logging
req.cookies in the createContext function its empty. I am thinking it could be something to do with Cors, which i am sure I already fixedits currently set in fastify like this: server.register(cors, {
origin: '*',
methods: '*',
credentials: true,
})Furthermore
my server.ts for trpc looks like this:
'use server'
import { cookies } from 'next/headers'
import { loggerLink, httpBatchLink } from '@trpc/client'
import { experimental_createTRPCNextAppDirServer } from '@trpc/next/app-dir/server'
import superjson from 'superjson'
import type { AppRouter } from '@api/server/router'
//console.log(cookies().toString())
export const api = experimental_createTRPCNextAppDirServer<AppRouter>({
config() {
return {
transformer: superjson,
links: [
loggerLink({
enabled: (opts) =>
process.env.NODE_ENV === 'development' ||
(opts.direction === 'down' && opts.result instanceof Error),
}),
httpBatchLink({
url: 'http://localhost:4000/trpc',
headers: {
cookies: cookies().toString(),
},
fetch(url, options) {
return fetch(url, {
...options,
credentials: 'include',
})
},
}),
],
}
},
})httpBatchLink({
url: 'http://localhost:4000/trpc',
headers: Object.fromEntries(headers()),
fetch(url, options) {
return fetch(url, {
...options,
credentials: 'include',
})
},
}),Basset Artésien Normand
damnit
thanks so much ðŸ‘
that worked. but it was weird because when logging
req.headers in the createContextit showed the cookie.