Skip to content

Commit

Permalink
docs: Update Streaming with Server Components docs to reflect correct…
Browse files Browse the repository at this point in the history
… usage (#7725)

* chore: update Streaming with Server Components docs to reflect correct usage

* chore: update Streaming with Server Components to show moving the getQueryClient function

* chore: fix prettier styling

---------

Co-authored-by: Dominik Dorfmeister <[email protected]>
  • Loading branch information
Aerilym and TkDodo committed Jul 17, 2024
1 parent 95d814a commit a1ce3c4
Showing 1 changed file with 25 additions and 5 deletions.
30 changes: 25 additions & 5 deletions docs/framework/react/guides/advanced-ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,9 @@ With the prefetching patterns described above, React Query is perfectly compatib

As of React Query v5.40.0, you don't have to `await` all prefetches for this to work, as `pending` Queries can also be dehydrated and sent to the client. This lets you kick off prefetches as early as possible without letting them block an entire Suspense boundary, and streams the _data_ to the client as the query finishes. This can be useful for example if you want to prefetch some content that is only visible after some user interaction, or say if you want to `await` and render the first page of an infinite query, but start prefetching page 2 without blocking rendering.

To make this work, we have to instruct the `queryClient` to also `dehydrate` pending Queries. We can do this globally, or by passing that option directly to `hydrate`:
To make this work, we have to instruct the `queryClient` to also `dehydrate` pending Queries. We can do this globally, or by passing that option directly to `hydrate`.

We will also need to move the `getQueryClient()` function out of our `app/providers.jsx` file as we want to use it in our server component and our client provider.

```tsx
// app/get-query-client.ts
Expand All @@ -378,15 +380,30 @@ function makeQueryClient() {
staleTime: 60 * 1000,
},
dehydrate: {
// per default, only successful Queries are included,
// this includes pending Queries as well
// include pending queries in dehydration
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === 'pending',
},
},
})
}

let browserQueryClient: QueryClient | undefined = undefined

export function getQueryClient() {
if (isServer) {
// Server: always make a new query client
return makeQueryClient()
} else {
// 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
// suspends 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
}
}
```

> Note: This works in NextJs and Server Components because React can serialize Promises over the wire when you pass them down to Client Components.
Expand Down Expand Up @@ -439,7 +456,7 @@ If you're using non-JSON data types and serialize the query results on the serve
import { QueryClient, defaultShouldDehydrateQuery } from '@tanstack/react-query'
import { deserialize, serialize } from './transformer'

export function makeQueryClient() {
function makeQueryClient() {
return new QueryClient({
defaultOptions: {
// ...
Expand All @@ -452,6 +469,8 @@ export function makeQueryClient() {
},
})
}

// ...
```

```tsx
Expand All @@ -461,11 +480,12 @@ import {
HydrationBoundary,
QueryClient,
} from '@tanstack/react-query'
import { getQueryClient } from './get-query-client'
import { serialize } from './transformer'
import Posts from './posts'

export default function PostsPage() {
const queryClient = new QueryClient()
const queryClient = getQueryClient()

// look ma, no await
queryClient.prefetchQuery({
Expand Down

0 comments on commit a1ce3c4

Please sign in to comment.