sannajammeh / trpc-swr

tRPC-ified SWR hooks
https://trpc-swr.vercel.app
MIT License
210 stars 6 forks source link

Documention/usage of withTRPCNext #53

Open laneme opened 8 months ago

laneme commented 8 months ago
// Copied from https://trpc-swr.vercel.app/server-side/setup#using-nextjs
import { withTRPCSWR } from "@trpc-swr/next"
const MyApp = ({ Component, pageProps }) => {
  return <Component {...pageProps} />;
};

export default withTRPCSWR({})(MyApp);

The import is renamed to withTRPCNext. The withTRPCNext function expects 2 arguments, and both of them cannot be empty apparently. The following line throws the error

export default withTRPCNext({}, {})(MyApp);

// error: Argument of type '{}' is not assignable to parameter of type 'CreateTRPCClientOptions<AnyRouter>'.

I tried passing the trpc config like below. But it still expects more the second argument to be fullfilled

export default withTRPCNext(
   {
      transformer: SuperJSON,
      // transformer: superjson, // optional - adds superjson serialization
      links: [
         httpBatchLink({
            url: `${process.env.NEXT_PUBLIC_API_HOST}`,
            fetch(url, options) {
               return fetch(url, { ...options, credentials: 'include' })
            },
         }),
      ],
   },
   {}, // Error
)(MyApp)

// Type '{}' is missing the following properties from type '{ createClient: CreateClient<AnyRouter>; useContext: () => TRPCContextType<AnyRouter>; Provider: TRPCProvider<AnyRouter>; SWRConfig: FC<...>; }': createClient, useContext, Provider, SWRConfigts

I'm not quite sure what to pass here. A hint would helpful. Heres my package versions.

"typescript": "~5.2.2",
"@trpc/client": "^10.43.1",
"@trpc/server": "^10.43.1",
"@trpc-swr/next": "^2.0.1",
"swr": "^2.2.4",
sannajammeh commented 8 months ago

Hi, apologies for the late answer! This is a documentation error. withTRPCNext is internal code which is exported for legacy reasons. I will be revisioning the documentation this week to split everything into plain react, Next App dir and Next pages dir. Glad you caught this, thanks for the issue!

Here is the correct usage:

// lib/trpc.ts
import type { AppRouter } from "@/server/_app";
import { createTRPCSWRNext } from "@trpc-swr/next";
import { httpBatchLink } from "@trpc/client";

export const api = createTRPCSWRNext<AppRouter>({
    links: [
        httpBatchLink({
            url: "/api/trpc",
        }),
    ],
})

// _app.tsx
import { api } from "@/lib/trpc"
export default api.withTRPC(MyApp)

Lets leave this issue open until documentation is improved.

laneme commented 8 months ago

Thank you for following up with this. I have one more question

Can we create server side helpers without access to the router and context?

According to the docs i need to create a ssr helper like this, which expects my context and router.

export const createSSR = () => {
    return createProxySSGHelpers({
        ctx: {}, // my context expects req,res,db etc
        router: trpcRoot,
    })
}

trpc has this docs for external routers. But thats for react-query. Is it possible to achieve this with trpc-swr?

sannajammeh commented 7 months ago

Its not possible with the SSG helpers unfortunately. SSG helpers are a wrapped version of router.createCaller.

You can get away with not passing context though, but that depends on what you actually need in your context. What's your use case for not passing in router, req res etc?

laneme commented 7 months ago

Yah and importing too. I have a fastify setup. Its a lil annoying to re-structure the router out of the backend module.

Importing router directly causes nextjs to process the backend which is set up and bundled somewhat differently. So I'm immediately greeted by some errors.

Having them separate has been really intuitive for me. Also useful for deploying them separetely. For example the nextapp to the edge and the backends to actual servers.

Thank you for clarifying thou. I'll figure somth out

sannajammeh commented 7 months ago

I also keep mine separate, but very separate so I can drag the tRPC router into any framework. You need modify the tRPC context and create two context adapter functions, one for next and one for fastify. Then you need one unified context which is the context type you'll use for the router itself, both of the functions should produce the same unified context in the end.

I definitely see the use case for this though. What you're asking for is the tRPC client to run on the server over http instead of createCaller and have the added SWR helpers for hydration etc.

Its definitely doable!

laneme commented 7 months ago

My bad lol misclick.

Thank you for the sugestion and yah this feature would indeed be helpful for users.

My suggestion would be to keep it in the roadmap, if this gets enough attention one day, this would be a worthwhile implemention.

sannajammeh commented 7 months ago

54 Is in canary right now with some changes for Next 14 AppDir.

Going to improve docs and refactor some more pages dir related code this week.