Skip to content

Rakkas - @tanstack/react-query integration with streaming SSR with Suspense support

Notifications You must be signed in to change notification settings

rakkasjs/tanstack-query

Repository files navigation

Rakkas Tanstack Query Integration

This repo contains an example of using Tanstack Query (formerly known as React Query) with Rakkas.

Open in StackBlitz

How does it work?

In short, we bypass Tanstack Query's own dehydration/hydration mechanism and do the serialization/deserialization ourselves by injecting scripts that call queryClient.setQueryData on the client side.

The file entry-hattip.tsx is Rakkas's server entry point and it contains Rakkas's server-side customization hooks. We use these hooks to serialize Tanstack Query's data into React's SSR stream.

The wrapApp hook is used to wrap the React app into a QueryClientProvider. A new query client is created for each request and its onSuccess hook is used to collect the data from each successful query.

The emitToDocumentHead hook is used to insert a small script into the document's head that contains the following:

$TQD = Object.create(null);
$TQS = (data) => Object.assign($TQD, data);

This defines a global object called $TQD (as in "Tanstack Query data") and a function called $TQS (as in "Tanstack Query set"). When $TQS is called with some data, it's merged into $TQD.

The emitBeforeSsrChunk is for injecting markup into React's SSR stream before each time React emits a chunk of HTML. We use it to inject a script that calls the $TQS function with the new data since the last time. The data is serialized with devalue, but JSON.stringify + some escaping would also work depending on your needs.

In entry-client.tsx, which is the client entry point of Rakkas, we take the data accumulated in $TQD and use queryClient.setQueryData to make it available to the client-side queries. We also overwrite the $TQS function to call queryClient.setQueryData from then on instead of stuffing the data into $TQD. We also delete the $TQD object to free up some memory.

We pass Date.now() to queryClient.setQueryData's updatedAt option. This is not really accurate but synchronizing clocks between the server and the client is not realistically feasible.

Finally, we use suspense: true when creating the query client to make sure all queries use Suspense by default. We also set less aggressive defaults to make debugging and observing the behavior easier.

You can uncomment the last few lines of layout.tsx to disable streaming and force React to wait until all suspense boundaries are resolved before emitting the HTML. This can make it easier to see what's going on.

TODO

  • Use Tanstack Query with useServerSideQuery
  • Create an "integration plugin" system for Rakkas to make this type of integration easier on the en user

About

Rakkas - @tanstack/react-query integration with streaming SSR with Suspense support

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published