Skip to content

feat: Make React-Query integration less opaque #4012

@sinclairnick

Description

@sinclairnick

Describe the feature you'd like to request

As per this discussion, I found it confusing to integrate tRPC into NextJS SSG, when not adhering to the strict Prisma/Next/tRPC paradigm.

Ultimately, I would like it to be more straightforward to integrate React Query.

Currently, the way tRPC integrates with React Query is fairly opaque, and having both @trpc/react-query and @trpc/next packages adds more confusion than benefit IMO.

Considering packages like react-query do a good job of handling the fetching, caching and SSG - and have all the up-to-date docs around it - I think tRPC would do well to integrate with such tools in a less opinionated manner, plugging into these existing tools, instead of encapsulating, limiting their behaviour and then having to document and maintain what is effectively a third party interface.

Describe the solution you'd like to see

Both the /react-query and /next packages are relatively small. Given the recommendation against tree-resolving the queries, here, and the general consensus among client-side fetching libraries like Apollo and React Query away from such approached, I think the /next package can actually be deprecated. It's not clear that the NextJS integration (for fetching) is required, and adds more overhead for documentation and more opportunity for confusion.

Secondly, I think the /react-query package could integrate with react-query in a more lightweight manner. Instead of in-housing the creation of QueryClient and QueryProvider, instead it should integrate within the /react-query approach. In short, the createTRPCReact should return a bunch of type-safe helpers proxying the some.query.here to an object of pre-defined useQuery, useInifiniteQuery etc. wrappers. I don't think any fundamentally new functionality or different API pattern (to react query) should be added here.

What might this look like?

Keep configuration of React Query entirely separate and up to the user. This maximises flexibility, transparency and minimizes tRPC maintenance + documentation.

// _app.tsx
const myQueryClient = new QueryClient(myOptions)

return <QueryProvider queryClient={myQueryClient}>
  <Hydrate state={myDehydratedState}>
    <Component {...} />
  </Hydrate>
</QueryProvider>

And then createTRPCReact can just return a comprehensive object of helper queries and exposure of helpful internal functions like so:

type AppRouter = { myProcedure: {...} }

const trpc = createTRRCReact<AppRouter>(trpcRelatedConfigHere)

// Using a procedure's helpers
trpc.myProcedure.useQuery(...)
trpc.myProcedure.useInfiniteQuery(...)
trpc.myProcedure.key(...) // <- useful for react-query idiomatic SSG
trpc.myProcedure.fetcher(...) // <- ^^

// Using TRPC helpers
```tsx
trpc.dehydrate() // <- Light wrapper over react query dehydrate, including appropriate serialisation/any necessary mods

Describe alternate solutions

Currently it's not clear that I can actually perform half the React Query things that I used to with tRPCs wrappers.

In the case of SSG, perhaps it's possible to create a vanilla client and react client, use getQueryKey and the vanilla client to re-enter the idiomatic react query approach a la

queryClient.prefetch(
  getQueryKey(...), // <- Key
  () =>. trpc.my.procedure.query(...) // <- fetcher
)
return { props: { trpcState: SuperJSON.serialize(dehydrate(queryClient)) } }

However I haven't been able to get this working just yet.

Additional information

I appreciate this suggestion is somewhat radical, and don't mean to come across as denigrating the work done here. I just think for the sanity of both the tRPC maintainers and users, integrating with already complicated tools like React Query should be done with minimal modification, lest you're on the hook for much more documentation, maintenance and functionality parity.

With all of this said, I'm more than happy to have a go at rethinking this. Of course, since it's a bold change, I wouldn't expect immediate acceptance. In any case, I'll be prototyping a solution like the above in my own application in the meantime, as SSG is a blocker for my migration to tRPC, so I can share or PR this solution when appropriate 👍.

Outside of this hurdle, I have been really enjoying using tRPC. In fact it inspired part of the API for another recent project of mine.

👨‍👧‍👦 Contributing

  • 🙋‍♂️ Yes, I'd be down to file a PR implementing this feature!

TRP-18

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions