rspc
rspc copied to clipboard
react integration: using ReactQueryDevtools inside RSPCProvider
Apologies if this is already fixed on master, I'm on @rspc/react 0.1.2 (and @tanstack/react-query 4.21.0, @tanstack/react-query-devtools 4.21.0)
So, react-query has a devtools widget that looks like this:
<QueryClientProvider client={queryClient}>
{/* The rest of your application */}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
Since `RSPCProvider is defined as
<Context.Provider
value={{
client,
queryClient,
}}
>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</Context.Provider>
I expected that I could just add a `ReactQueryDevtools tag inside it, like this
<RSPCProvider client={client} queryClient={queryClient}>
<ReactQueryDevtools initialIsOpen={true} />
</RSPCProvider>
But this is met with an inescrutable error
See error message
error - [rendering] [root of the dev server]/ Error during SSR Rendering
TypeError: __TURBOPACK__imported__module__$5b$project$2d$with$2d$next$5d2f$node_modules$2f2e$pnpm$2f$next$40$13$2e$1$2e$1_biqbaboplfbrettd7655fr4n2y$2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$react$2e$shared$2d$subset$2e$js__.createContext is not a function
at <unknown> (/node_modules/.pnpm/@[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/@tanstack/react-query/build/lib/QueryClientProvider.mjs:3:43) [<unknown> (.next/server/app/chunks/rsc/_87ae68.js:7003:252)]
at Module.[project-with-next]/node_modules/.pnpm/@[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/@tanstack/react-query/build/lib/QueryClientProvider.mjs (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:7045:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at <unknown> (.next/server/app/chunks/rsc/_87ae68.js:6895:265)
at Module.[project-with-next]/node_modules/.pnpm/@[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/@tanstack/react-query/build/lib/useQueries.mjs (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:6975:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at <unknown> (.next/server/app/chunks/rsc/_87ae68.js:6852:256)
at Module.[project-with-next]/node_modules/.pnpm/@[email protected]_biqbaboplfbrettd7655fr4n2y/node_modules/@tanstack/react-query/build/lib/index.mjs (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:6876:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at <unknown> (.next/server/app/chunks/rsc/_87ae68.js:250:251)
at Module.[project-with-next]/node_modules/.pnpm/@[email protected]_67mjlkwmhckybkh7pbuxjzh4me/node_modules/@tanstack/react-query-devtools/build/lib/devtools.mjs (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:988:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at <unknown> (.next/server/app/chunks/rsc/_87ae68.js:230:278)
at Module.[project-with-next]/node_modules/.pnpm/@[email protected]_67mjlkwmhckybkh7pbuxjzh4me/node_modules/@tanstack/react-query-devtools/build/lib/index.mjs (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:241:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at <unknown> (.next/server/app/chunks/rsc/_87ae68.js:10:275)
at Module.[project-with-next]/app/page.tsx (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:43:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at <unknown> (.next/server/app/chunks/rsc/_87ae68.js:113:92)
at Module.[project-with-next]/app/page.tsx/layout-entry.tsx (ecmascript, rsc) (.next/server/app/chunks/rsc/_87ae68.js:126:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at getOrInstantiateModuleFromParent (.next/server/app/chunks/ssr/_790a59.js:69040:12)
at esmImport (.next/server/app/chunks/ssr/_790a59.js:68769:20)
at Module.default (.next/server/app/chunks/rsc/_87ae68.js:130:18)
at <unknown> (/app/entry:20:21) [<unknown> (.next/server/app/chunks/ssr/_790a59.js:191:165)]
at Module.[project-with-next]/app/entry (ecmascript, ssr) (.next/server/app/chunks/ssr/_790a59.js:383:3)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68959:21)
at runModuleExecutionHooks (.next/server/app/chunks/ssr/_790a59.js:68998:5)
at instantiateModule (.next/server/app/chunks/ssr/_790a59.js:68958:5)
at instantiateRuntimeModule (.next/server/app/chunks/ssr/_790a59.js:69548:12)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:68601:1)
at <unknown> (.next/server/app/chunks/ssr/_790a59.js:69599:39)
at <anonymous>
at Object.registerChunk [as push] (.next/server/app/chunks/ssr/_790a59.js:69599:25)
at Object.<anonymous> (.next/server/app/chunks/rsc/_87ae68.js:1:41)
at Module._compile (node:internal/modules/cjs/loader:1165:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1219:10)
at Module.load (node:internal/modules/cjs/loader:1043:32)
at Function.Module._load (node:internal/modules/cjs/loader:878:12)
at Module.require (node:internal/modules/cjs/loader:1067:19)
at require (node:internal/modules/cjs/helpers:103:18)
at Object.<anonymous> (.next/server/app/index.js:4:1)
at Module._compile (node:internal/modules/cjs/loader:1165:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1219:10)
at Module.load (node:internal/modules/cjs/loader:1043:32)
at Function.Module._load (node:internal/modules/cjs/loader:878:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at <unknown> (node:internal/main/run_main_module:22:47)
| Node.js exit code: 1
I have NODE_ENV=development
set so this can't be it.
PS: Another issue is that I can't add multiple children to RSPCProvider
. I think that's because {children}
is defined as children?: ReactElement;
which means it can have zero or one children. Adding a component inside QueryClientProvider
which in turn has ReactQueryDevtools
inside it doesn't work either: it doesn't error like this but it mysteriously isn't shown.
It looks like I forgot to update the docs when I changed how this is handled a while back. I will make sure I do that. Try the following:
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<RSPCProvider client={client} queryClient={queryClient}>
<App />
</RSPCProvider>
</QueryClientProvider>
I could be wrong but based on that error it also kinda looks like your Next 13 app directory which will not play nicely with rspc (or Tanstack Query as far as I'm aware) on the server side, ensure you are "use client";
'ing the file with mounts the provider and all files using the hooks. I am not sure what Vercel recommendations are but maybe I should do that in rspc.
It's also worth noting rspc doesn't have official support for SSR so your mileage may vary with that use case. Although do feel free to file bugs you find with it and I will look into them.
Personal Notes related to this:
- The documentation should reflect the need for adding
QueryClientProvider
aboverspc.Provider
- Show an example of using React Query devtools for clarity.
- I thought I fixed the children type issue but maybe that was only on the SolidJS client
Yes I'm on next 13 app directory. When adding "use client";
this error is gone but I got other strange errors (but I gave up on react-query devtools for now and deleted everything)
And this might be off topic for this issue but, what's the blocker for rspc being supported on ssr? Is it just a matter of testing?
And.. if rspc doesn't support SSR, does it make sense for the example use FetchTransport
on server and WebsocketTransport
on client here? (or httpLink
and wsLink
on main). I mean, when running on server it will do ssr..
To jump in on this, I also experienced some weirdness with [email protected] in Next.
I'm not using the app directory (it's... clearly not ready for prime-time yet, and neither is the rest of the React ecosystem). But I am using Tauri and statically exporting my site with next export
.
I found I had to do this, otherwise rspc would throw on server render:
export let client;
if (typeof window !== "undefined") {
const { createClient } = require("@rspc/client");
const { TauriTransport } = require("@rspc/tauri");
client = createClient<Procedures>({
transport: new TauriTransport(),
});
}
For what it's worth, there's multiple levels of "SSR support" -- generally the minimum level is that a library does nothing during SSR, which is often fine. (For example, React Query has explicit SSR support via a few mechanisms, the most basic of which is to not attempt any query until it's hydrated client-side.) This might already be fixed on main
, but I think it would be nice if rspc were similarly well-behaved.
I will give this a look when I have some time.
I am probably not going to officially support the Next 13 app directory until TanStack Query (and probably also tRPC) do officially because I would like to see the patterns they come up. However, that doesn't mean it won't work, I just won't recommend it's usage.
It would probably make the most sense, for now, to use the @rspc/client
within Server Components (const data = await rspc.query(...)
) for now and just the regular @rspc/react
for Client components. This doesn't deal with hydrating React Query which depending on your use-case will cause the data to be double-fetched (once on server and once on client) but given Next.js App directory is in beta I don't think these things have been worked out yet.
I recall you being able to do something like this when Next 13 launched to trick it into treating external packages as client components which you may need to do to correctly attach the context provider. This is something I will likely build into rspc I just need to check if Vercel recommend me adding "use client";
or not.
"use client";
export * from "@rspc/react";
In terms of SSR support with the non-app directory and SolidStart that is definitely something I would accept PRs for and will work on when I am able to dedicate the time to it. If TanStack Query has SSR support I suspect nothing would stop you from just using although because I haven't tested it I wouldn't be surprised if you run across issues (although file them here or in a separate GH issue).
I wonder if the example shown by @lostfictions is not working because of the createClient
or the TauriTransport
? I can pretty much guarantee the Tauri transport won't work with SSR and that given Tauri uses a Rust backend logically that doesn't make sense to support. If the createClient
call is the issue let me know and I will look at fixing that because it's unintended.
In terms of this @dlight as I didn't do the Next.JS example (it was a PR) I am not sure. It's possible Next.JS don't support the browser Websocket
API (haven't checked) or most likely it's because you shouldn't open a subscription server-side given as far as I am aware GSSP and the SSR are returned directly to the page and not streamed so it couldn't do real-time updates which is the whole point of a subscription.
Fair enough!
About the websocket thing: it will actually error when doing ssr, but what I actually need is subscriptions (which isn't very well supported by react-query so I'm not even using it, I just wrap on a useReducer
)..
I tried some approaches for disabling SSR (using dynamic imports would give a DYNAMIC_SERVER_USAGE error; and another approach would give an error I forgot about), none successful, so I ended up doing lostfictions's trick and websockets finally work.
So I guess ReactQueryDevtools
will work now? (haven't tested though)
I tried some approaches for disabling SSR (using dynamic imports would give a DYNAMIC_SERVER_USAGE error; and another approach would give an error I forgot about), none successful, so I ended up doing lostfictions's trick and websockets finally work.
hmm, that's odd... dynamic(() => import('./my-component'), { ssr: false })
always works for me for any kind of interop work i've ever had to do (binding non-react components, webgl and audio, sockets, you name it). again, i suspect the app
directory is at fault here -- i know they anounced it very bombastically at their conference, but everything then and now points towards it really not being ready for widespread use, and weirdness and breakage are going to be par for the course for months. (iirc some of the features they announced at next conf were based on react RFCs that were still in discussion at the time!)
I wonder if the example shown by @lostfictions is not working because of the
createClient
or theTauriTransport
? I can pretty much guarantee the Tauri transport won't work with SSR and that given Tauri uses a Rust backend logically that doesn't make sense to support. If thecreateClient
call is the issue let me know and I will look at fixing that because it's unintended.
i'll take a look at the source for the tauri transport when i can -- but i do want to note that tauri offers a next.js template as part of their blessed workflow, and as far as i remember said template doesn't require the use of workarounds like next/dynamic
or checking for the presence of window
. so i suspect there may be something specific to what rspc is doing in this case.