upstash/jstack

Suspense Queries & Hono

Opened this issue · 2 comments

I think you can replace this code

jstack/src/app/page.tsx

Lines 13 to 24 in ee3f48a

/**
* This is the intended way to prefetch data on the server to have it immediately available in the client.
* But: you could also just pass the post as a prop instead of using the `HydrationBoundary`
*/
const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryFn: () => recentPost,
queryKey: ["get-recent-post"],
})
return (

with an even easier implementation by using ReactQueryStreamedHydration and with useSuspenseQuery. I use such in production and have no issues and don't need to prefetch queries by hands.

// <providers>/ReactQuery.ts
'use client'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'
import * as React from 'react'

function makeQueryClient() {
  return new QueryClient()
}

let browserQueryClient: QueryClient | undefined

function getQueryClient() {
  if (typeof window === 'undefined') {
    // Server: always make a new query client
    return makeQueryClient()
  }
  // Browser: make a new query client if we don't already have one
  // This is very important so we don't re-make a new client if React
  // supsends during the initial render. This may not be needed if we
  // have a suspense boundary BELOW the creation of the query client
  if (!browserQueryClient) browserQueryClient = makeQueryClient()
  return browserQueryClient
}

export function ReactQueryProvider(props: { children: React.ReactNode }) {
  const queryClient = getQueryClient()
  // NOTE: Avoid useState when initializing the query client if you don't
  //       have a suspense boundary between this and the code that may
  //       suspend because React will throw away the client on the initial
  //       render if it suspends and there is no boundary

  return (
    <QueryClientProvider client={queryClient}>
      <ReactQueryStreamedHydration>
        {props.children}
      </ReactQueryStreamedHydration>
    </QueryClientProvider>
  )
}

but also be aware that if a transformer is used in trpc you'll have to pass it to ReactQueryStreamedHydration too.


On the Hono part. Why is it really needed? I had projects with trpc without Hono and they worked fine.

Also fyi hono has a full-typed fetcher that I use instead of trpc nowadays.
It doesn't have a native transport support (like superjson), but it is quite easy to write one yourself.

im kinda confused by this issue. There is no trpc here, the built-in hono fetcher is how we achieve type-safety in the first place and the superjson implementation already exists. If we can find a good way to make the streamed hydration possible w/ the superjson integration I dont see why not

im kinda confused by this issue. There is no trpc here, the built-in hono fetcher is how we achieve type-safety in the first place and the superjson implementation already exists. If we can find a good way to make the streamed hydration possible w/ the superjson integration I dont see why not

oh lol i haven't checked the code and assumed by the file layout it's trpc. great job!

then focusing on the streamed hydration only.
It is possible by passing transformer prop to ReactQueryStreamedHydration.