trpc: `@trpc/next` with `ssr: true` breaks `getServerSideProps`
Notes by @KATT:
- Solving this is blocked by https://github.com/vercel/next.js/discussions/28183.
- Keeping this open for visibility, but it likely won’t be fixed.
- See warning-block at https://trpc.io/docs/ssr
@trpc/next: 8.0.0-alpha.6
Using:
export default pipe(
App,
withTRPC({
ssr: true,
config: (_ctx) => ({
url: "http://localhost:3000/api/trpc",
queryClientConfig: {
defaultOptions: {
queries: {
staleTime: 600
}
}
}
}),
})
)
Any page with getServerSideProps, for example:
export const getServerSideProps: GetServerSideProps<Props> = async () => {
return {
props: {
user: {
name: 'x',
email: "y"
}
}
}
}
Will receive undefined props, then get refreshed with props (the latter usually never executes due to errors using undefined)
Removing withTRPC hof stops this behavior.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 9
- Comments: 33 (19 by maintainers)
Commits related to this issue
- issue-596 shows #596 being a non-issue — committed to trpc/trpc by KATT 3 years ago
- fix: disable trpc ssr because it breaks getServerSideProps bug issue https://github.com/trpc/trpc/issues/596 essentially revert cc09f7425d25b2b17e3e66f44400fe4029f46c69 — committed to mkraenz/meetmecal by mkraenz a year ago
Alex, I truly appreciate what you’ve done with this library and I understand that this is a limitation of Next.js.
I’m glad we have a workaround and I don’t mean to put pressure on you to deliver anything here. Thanks again for the solid lib.
For me, the main value of TRPC is a typesafe API between my frontend and my backend using shared types. The rest is just gravy on top 😃
@apieceofbart there are two independent things that aren’t exactly the same.
getServerSidePropscan be used when rendering component on server or client.IIRC, its a while back:
the option
ssrintrpconly affects the rendering of JSX/TSX server-side. It usesgetInitialProps. But ingetInitialPropsyou don’t get access to the result ofgetServerSideProps- this is why its currently undefined withssr: true. When you setssr: falseyou do not disablegetServersideProps, so everything that comes from it as a result can be rendered server-side, once thessrfeature is disabled, because thengetInitialPropsis not used.I’m a one man band making tRPC, all example projects, and docs… there are limits to what I have bandwidth to do. Super keen to take on pull requests from contributors with the gaps as you learn the edge cases.
This issue of combining getSSR+getSSG and getInitialProps is out of my hands to fix as it’s an issue with Next.js - if you have ideas for workarounds, they are welcome as well.
If you encounter this, set
ssr: falsein your_app.tsx.I just encountered this issue. I wanted to use
getServerSidePropsfor authorization but the page still gets rendered before the props gets loaded (and then re-rendered after that).Steps to reproduce: Create a sample project
npx create-next-app --example https://github.com/trpc/trpc --example-path examples/next-prisma-starter trpc-prisma-starterCreate
src/pages/home.tsxGoing to
localhost:3000/homewill log the following in the server’s console:Expected:
getServerSidePropsgets called before the Home page is rendered. The page gets rendered with a fullpropsobject.Actual:
getServerSidePropsis then called and the page is re-rendered with the props.This issue seems valid after all. Sorry for initially closing it. It’s for the same as urql can’t do it, see here - https://github.com/FormidableLabs/urql/discussions/1091.
I’m doing some exploratory stuff to see if there’s a workaround.
@akomm Thank you for your comment - I do not fully understand it but I’ll read some more about trpc. From what I understand it uses
getInitialPropsbehind the scenes whenssris set totrue.Default GH search includes all closed issues, so this issue will still pop up when searching for
getServerSidePropsorssr(more keywords, yay) in case someone wants to read on this issue. If more people will report this instead of searching, we can reopen/pin it.@KATT Should this issue be closed if its a
wontfix?getServerSideProps: user clicks ->routeChangeStart--> ⏳ […delay] -->routeChangeCompletegetInitialProps: user clicks ->routeChangeStart--> 🚀 instant -->routeChangeCompleteThe difference is that you’ll have to handle the loading client-side with getInitialProps.
For an implementation of this with tRPC doesn’t require a loading you can check out https://typescript.careers which optimistically loads the data of all routes on mount (as 1 single batch request), making navigation feel instant.
If you use
getStaticPropsyou can get instant loading as well.See https://nextjs.org/docs/api-reference/next/router#routerevents
That’s what we do in tRPC - see https://github.com/trpc/trpc/blob/main/packages/next/src/withTRPC.tsx#L85
Thanks for the elaborate answer, @akomm! ❤️
I very much agree with your approach 🙏
I evaluate the benefit of a library vs. cost of patching and rewiring things to own needs (plus the hidden cost to keep adjusting those adaptations with updates). Based on that I either live with things not perfectly fit and adjust them, or I do it myself, or I use alternative (in this case I just do it myself).
In general, I’d rather write some code myself than adding a library. If the cost is not high. I have lot of projects to maintain and I want it to be as simple as possible. Every thing that does not fit or has to be “adapted” artificially to match, and the adaptation looks like ugly code, is a problem I try to avoid. On top of it, you are hooked to get things fixed to release cycles or hand-wiring fix-commits in dependencies…
I figured out for my need of typed API and elimination of redundancy, it does not take much (using fp-ts/io-ts). And I don’t need to create “type adapters” etc, for things to work nicely. Also: libraries will always be opinionated in some way.
As about the problem: I’d probably find the exact situation in which the problem occurs, but there are so many bugs all over the place (in other libraries), that I just don’t have the time messing with all them. At times I’d jump from one bug in a package to another bug in the same package. And sometimes I can’t just replace it with own code (cost to high).
The other way around examples: nextjs or pdf parser is something - to name an example - I would rather take the adjusting, than the cost of doing AND maintaining it myself.