Skip to content

docs(ssr): add experimental app directory guide #4568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jan 25, 2023
Merged

Conversation

efilion
Copy link
Contributor

@efilion efilion commented Nov 28, 2022

Adding Next.js 13 app directory docs discussed in #4558.

The initialData approach was first published by @lukemorales. This approach appears to be subject to the same caveats as with using initialData in the standard pages directory. Having to thread initialData through to a component deep down in a component tree is aggravated by now having to fetch data in an ancestor Server Component.

Given those drawbacks, I've also documented an approach that rehydrates the Query Cache. This approach was largely informed by Using Other Frameworks or Custom SSR Frameworks. There are two notable deviations from that guide:

  • Not calling queryClient.clear(). As per @TkDodo, this is no longer necessary since v4.
  • Not populating window.REACT_QUERY_STATE with dehydratedState. Next.js is handling hydration without any need for this.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 28, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 9fd54ef:

Sandbox Source
@tanstack/query-example-react-basic-typescript Configuration
@tanstack/query-example-solid-basic-typescript Configuration
@tanstack/query-example-svelte-basic Configuration
@tanstack/query-example-vue-basic Configuration

Copy link
Collaborator

@TkDodo TkDodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. I would like to structure it a bit differently:

let's keep everything as it is for the nextJs (12) docs and start a new section at the bottom of this page called Experimental app directory in Next 13 or something. There, we can put the initialData and Hydrate approaches, with another notice that this is experimental and best practices might change as we figure things out :)

Comment on lines 199 to 200
<QueryClientProvider client={queryClient}>
<Hydrate state={dehydratedState}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be able to decouple QueryClientProvider and Hydrate. The Provider needs to go at the top, once. Nothing changes here really.

Hydrate can appear multiple times in the app tree. It just takes data and puts it into the cache if it's newer, as opposed to initialData, which will only write data once to the cache if there is no data yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decoupling it is a really good point. In the current implementation, you might end up prefetching data at the top level for a leaf component that is conditionally rendered. Effectively, you could end up prefetching data that isn't needed in the end. Fetching data closer to the component that needs it could also allow you to parameterize that fetch with arguments that wouldn't be available at the top level.

I'll play around with these ideas a bit and see what kind of new implementation I can get working. Thinking something along the lines of a higher-order component that does the fetching and wraps its argument in a Hydrate.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say keep it simple for now, the API is probably going to change in the next RQ major anyway. If you wrap QueryClientProvider higher up in the tree, you can just do:

'use client';
import { Hydrate } from '@tanstack/react-query'

export default function HydrateOnClient(dehydratedState) {
  return <Hydrate state={dehydratedState}>{children}</Hydrate>;
}

and use that directly in the Server Components. Don't think there is need for a HoC or something more complex here (at least yet).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://codesandbox.io/p/github/efilion/next13-react-query/decoupled-hydrate?file=%2Fapp%2Fpage.tsx

The HoC isn't strictly necessary, but it helps hide some of the complexity and keep things DRY.

To take advantage of the deduplication provided by QueryClient, the instance defined at the page level will need to be threaded down through to all components looking to prefetch data. That nullifies one of the advantages of the Hydration approach over the InitialData approach. It would be nice to have something akin to an IoC container that could provide a QueryClient as a request-scoped singleton, but I didn't see much in the way of options to accomplish that at the moment. InversifyJS and TSyringe don't fit the bill here. Likely a difficulty with the fact that being single-threaded, Node.js doesn't provide each request its own thread. Nest.js has a solution, so maybe Next.js could implement this itself down the line. Alternatively, can look at the Reader Monad pattern from functional programming to handle dependency injection.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a tricky one, clever solution!

I worry about putting that much complexity in the docs though, especially for an experimental approach, might fit better as an example to link to? There might be another way as well, not saying it's better but I thought I'd throw it out there.

So behind the scenes we have RSCs, client (server rendered) and client (browser rendered). For both of the client parts, it's important to have the same queryClient throughout the whole rendering which is why we want to hoist it to the top, but for the RSCs, your initial approach is actually fine where you create a new queryClient for each RSC (fine as in works, not as in pretty, DRY, fast etc). The reason for this is that since that data gets de/rehydrated anyway, we only need the queryClient as a way to be able to call prefetchQuery and get the right format back when we call dehydrate. The fetches themselves will be deduped behind the scenes anyway, so even if two RSCs call the same endpoint, it at least wont double fetch.

So for RSCs specifically, it's fine to duplicate the queryClient instead of passing it around. Ugly and not something we want long term, but might be easier and more concise to document, although possibly more confusing?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it helps hide some of the complexity and keep things DRY.

I guess another way of stating the above is that I'm not sure this is something we should aim to do at this point, I kind of like having the full extent of the experimental and raw nature of this fully visible, it becomes less of an "officially endorsed pattern" that way which is something that might bite us later (even with caveats, some devs will just copy-paste it). 😅

Maybe I worry too much though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for RSCs specifically, it's fine to duplicate the queryClient instead of passing it around. Ugly and not something we want long term, but might be easier and more concise to document, although possibly more confusing?

Fortunately, I finally stumbled across the section on Per-request Caching. That will allow me to create the request-scoped singleton I wanted without even having to bring in a 3rd party dependency. This way we only ever have to deal with a single value of dataUpdateAt even if multiple components use the same query.

My only concern now is dehydrating only the queries relevant to the component being wrapped in <HydrateOnClient>. Trying to avoid sending more data than necessary. Wondering if we should think about extending the dehydrate API to match on queryKey/queryHash to improve on time complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it helps hide some of the complexity and keep things DRY.

I guess another way of stating the above is that I'm not sure this is something we should aim to do at this point, I kind of like having the full extent of the experimental and raw nature of this fully visible, it becomes less of an "officially endorsed pattern" that way which is something that might bite us later (even with caveats, some devs will just copy-paste it). sweat_smile

Maybe I worry too much though.

I see what you mean. My HoC approach could be a better match for a blog post.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://codesandbox.io/p/github/efilion/next13-react-query/hydrated-content?file=%2Fapp%2FhydratedContent.tsx

Mainly looking to improve on line 12 inside hydratedContent.tsx. Not setting anything at all here might be the best approach for the moment. Might need to make a change to dehydrate to pick and choose which queries to dehydrate based on queryKey. Open to suggestions.

@efilion
Copy link
Contributor Author

efilion commented Nov 29, 2022

let's keep everything as it is for the nextJs (12) docs and start a new section at the bottom of this page called Experimental app directory in Next 13 or something. There, we can put the initialData and Hydrate approaches, with another notice that this is experimental and best practices might change as we figure things out :)

Agreed. My instinct was to have them together because they share things in common, and I didn't want to be too repetitive, but I'm not writing an essay here and the goal isn't to compare and contrast. When people read this, they'll just choose to read one section, so being repetitive isn't as bad. Better not to disrupt the flow of documentation that people are already used to or to introduce experimental stuff before fully addressing the more standard approach.


export default async function Providers({children}) {
const queryClient = new QueryClient()
await queryClient.prefetchQuery(['posts'], getPosts)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems really backwards that you gotta await queryClient.prefetchQuery(['posts'], getPosts) in order for the state to be hydrated...

I would expect some magic to hydrate anything that has been called with useQuery(..., { suspense: true }) automatically

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a missing API in React for this at the moment? No way of pushing state from a server-render React-component to a client-side one without this stuff?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Server-side suspense is a whole other wrinkle I hadn't considered. Dropping reactwg/react-18#37 here for reference because I'll likely want to circle back on this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this could be handled better by TanStack/query, but for now, it is what it is :). This is exactly why I'd like the whole section to be marked as experimental - because the recommendations might change.

also looping in @Ephem :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, the recommendation should always be to prefetch things as early as possible, both to get a headstart and to avoid waterfalls where you suspend in A to be able to render B which then suspend again etc. We should definitely investigate supporting the other case as well though (if it's even going to be possible), but that's for the future.

One caveat is that currently you have to await the data in the RSC, which blocks streaming what you can early. What we really want is to start prefetching in the RSC but not await it, instead suspending in the component that needs this data. That will require both that React implements de/hydration of Promises and a bunch of changes to RQ though, so I think this PR (with the proposed changes elsewhere) documents the best current experimental approach.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and like we talked about on Discord @KATT, I think it's interesting here to think about how to support "normal" streaming rendering without RSCs as well. A lot of frameworks might implement streaming rendering without RSCs, so that's also something we want to support.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, for now we should definitely document that useQuery(..., { suspense: true }) wont work on the server unless you have already prefetched that data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you've already prefetched your data, is there any utility to set a client-side suspense boundary? If you don't prefetch, you can set suspense boundaries inside a client-side component and use useQuery(..., { suspense: true }). Data will start fetching after the page loads. If you're prefetching, you can set a suspense boundary in a server-side component, and there's no need for { suspense: true } inside useQuery. Data will start fetching as soon as possible, the server will send a response without waiting for it, and then stream the rendered component to be integrated into the page once the fetching completes.

@@ -111,6 +180,95 @@ function Posts() {

As demonstrated, it's fine to prefetch some queries and let others fetch on the queryClient. This means you can control what content server renders or not by adding or removing `prefetchQuery` for a specific query.

#### With experimental `app` directory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add a big :::caution under here that this is experimental and is subject to change awaiting {{some link to a React-issue or RFC}}


Prefetch your data inside a Server Component and provide your previously defined Client Component with the dehydrated state of the server-side `QueryClient`.

- Create a new QueryClient instance **for each page request. This ensures that data is not shared between users and requests.**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rephrase this somehow

Suggested change
- Create a new QueryClient instance **for each page request. This ensures that data is not shared between users and requests.**
- Create a new QueryClient instance **within the body of the React component**. This ensures that data is not shared between users and requests.

Copy link
Collaborator

@Ephem Ephem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work on this so far! In a longer time perspective I think we have a lot to figure out about how to document and teach this for different cases, frameworks etc, but don't think there is much use in doing that before we figure out what the "next generation" of hydration etc is going to look like, this looks like a good stopgap for now for people that want to experiment. 😄

React Query supports both of these forms of pre-rendering regardless of what platform you may be using

### Using `initialData`

The setup is minimal and this can be a quick solution for some cases, but there are a **few tradeoffs to consider** when compared to the full approach:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this section! It's been sorely missing, glad you included it, and well written. 😄

Comment on lines 199 to 200
<QueryClientProvider client={queryClient}>
<Hydrate state={dehydratedState}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say keep it simple for now, the API is probably going to change in the next RQ major anyway. If you wrap QueryClientProvider higher up in the tree, you can just do:

'use client';
import { Hydrate } from '@tanstack/react-query'

export default function HydrateOnClient(dehydratedState) {
  return <Hydrate state={dehydratedState}>{children}</Hydrate>;
}

and use that directly in the Server Components. Don't think there is need for a HoC or something more complex here (at least yet).


export default async function Providers({children}) {
const queryClient = new QueryClient()
await queryClient.prefetchQuery(['posts'], getPosts)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, the recommendation should always be to prefetch things as early as possible, both to get a headstart and to avoid waterfalls where you suspend in A to be able to render B which then suspend again etc. We should definitely investigate supporting the other case as well though (if it's even going to be possible), but that's for the future.

One caveat is that currently you have to await the data in the RSC, which blocks streaming what you can early. What we really want is to start prefetching in the RSC but not await it, instead suspending in the component that needs this data. That will require both that React implements de/hydration of Promises and a bunch of changes to RQ though, so I think this PR (with the proposed changes elsewhere) documents the best current experimental approach.

@codecov-commenter
Copy link

codecov-commenter commented Dec 10, 2022

Codecov Report

Base: 96.36% // Head: 91.25% // Decreases project coverage by -5.11% ⚠️

Coverage data is based on head (08d6c84) compared to base (eab6e2c).
Patch has no changes to coverable lines.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4568      +/-   ##
==========================================
- Coverage   96.36%   91.25%   -5.11%     
==========================================
  Files          45      110      +65     
  Lines        2281     4116    +1835     
  Branches      640     1057     +417     
==========================================
+ Hits         2198     3756    +1558     
- Misses         80      339     +259     
- Partials        3       21      +18     
Impacted Files Coverage Δ
src/core/notifyManager.ts
src/core/subscribable.ts
src/core/query.ts
src/core/utils.ts
src/devtools/useLocalStorage.ts
src/react/useIsMutating.ts
src/devtools/devtools.tsx
src/devtools/theme.tsx
src/core/queryCache.ts
src/devtools/utils.ts
... and 145 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@efilion
Copy link
Contributor Author

efilion commented Dec 12, 2022

Line 218: Wondering if it would be a good idea to mention that eventually 'use client' will be added to react-query modules or that this is still being evaluated.

@efilion
Copy link
Contributor Author

efilion commented Dec 12, 2022

Line 248: Looking only to dehydrate the queries that were prefetched in the Server Component. Could export matchQuery from query-core, but will need to make the types match, and time complexity would be less than ideal. Alternatively, could expand the dehydrate API to accept a list of queryKeys that can be looked up by queryHash.

@Ephem
Copy link
Collaborator

Ephem commented Dec 12, 2022

I haven't had time yet to look at the latest changes here (soon!), but I thought I'd note that I've written a braindump discussion "React Streaming SSR/Server Components" that relates to this PR.

@efilion
Copy link
Contributor Author

efilion commented Dec 12, 2022

I haven't had time yet to look at the latest changes here (soon!), but I thought I'd note that I've written a braindump discussion "React Streaming SSR/Server Components" that relates to this PR.

Thanks for writing this up! Tons of really useful background/context. Will take a bit for me to digest all of it and get up to speed.

Already, I'm thinking I should just drop the query cache filtering on line 248, and wait to see what new API will be settled on. Maybe I make a note that the current approach serializes and sends more duplicate data to the client than necessary, but that this will be addressed in a later update.

Also, I think I still need to think more thoroughly about what will happen with my current approach if someone opts in to concurrent features... especially Suspense. I can see that the query cache could look different between the time a component renders on the server and the time it hydrates on the client. Two components share a query that wasn't prefetched on the server, one component hydrates and fetches the query before the second can hydrate. Or maybe a component has access to data on the server because the query was already prefetched by another component, but then on the client it hydrates before the component with the <Hydrate> wrapper can rehydrate the query cache with the prefetched query. Even refetching of a query that was initially prefetched on the server could be problematic.

@Ephem
Copy link
Collaborator

Ephem commented Dec 13, 2022

sends more duplicate data to the client than necessary

Yeah, this can be a tradeoff in some cases, but I think compression (gzip/brotli) might take care of a lot of that since the data would be identical, and I'm not sure if React itself might even try to do something smart here when props are identical? Still something to keep an eye on though.

I can see that the query cache could look different between the time a component renders on the server and the time it hydrates on the client

When we fix useSyncExternalStore should have a correct/frozen getServerSnapshot (minor), that will take care of this. That makes it so during hydration, whenever that happens, all RQ hooks etc reads the original data that was passed down from the server, even if it has later changed. 😃

After hydration has happened, the component would rerender with the fresh data. This does mean that unhydrated components will be stale while others might have already updated though, but that's unavoidable with incremental hydration.

export default getQueryClient
```

Re-export the `<Hydrate>` component as a Client Component. This allows `<Hydrate>` to execute on the client and make use of client-only features. **TODO: Plans to add 'use client' to react-query modules?**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add: This is a temporary workaround until 'use client' is eventually added directly into the react-query modules.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we have plans to do this. @Ephem this is something we could even do for v4, right?

await queryClient.prefetchQuery(['posts'], getPosts)
const dehydratedState = dehydrate(queryClient, {
dehydrateMutations: false,
shouldDehydrateQuery: query => true // TODO: matchQuery or extend dehydrate
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop this for now and simply have const dehydratedState = dehydrate(queryClient)

Add an acknowledgement that more duplicate data than strictly needed is being serialized and sent to the client, and that this issue is being looked at for a future update.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, we should probably just use the default settings here. There likely are no mutations, so setting dehydrateMutations to false doesn't accomplish much

@efilion efilion marked this pull request as draft December 15, 2022 19:44
@HamAndRock
Copy link

Hey, trying to use the Hydrate approach but getting this error, when adding the dehydrate() step to server component, runninng "@tanstack/react-query": "^4.22.0".

image

Is this supposed to happen since this is still a draft ?

@Ephem
Copy link
Collaborator

Ephem commented Jan 16, 2023

@HamAndRock That's weird. Some questions:

  • Does this happen even if you only call dehydrate, but not the Hydrate component?
  • If yes, where are you importing dehydrate from? It lives in the @tanstack/query-core package, so just importing and using that should absolutely not give you that error (but it's also re-exported in @tanstack/react-query which is why I'm asking)
  • If it only happens with the Hydrate component, did you remember to wrap it in a HydrateOnClient component with 'use client' on top?

@HamAndRock
Copy link

Hey, thank you for answer, the issue was in the import of dehydrate like you mentioned I used autocomplete to import it and it picked the react-query version instead of query-core.

I am sorry, this is my fault for wasting your time. I suggest maybe adding some kind of warning to the docs about these two "identical" imports, so it's easier to find the issue faster.

Thank you again and sorry for me being not able to copy code :D

@TkDodo
Copy link
Collaborator

TkDodo commented Jan 16, 2023

@Ephem @efilion what would it take for us to get this from a draft PR to something that we can merge?

@efilion
Copy link
Contributor Author

efilion commented Jan 16, 2023

Hey, thank you for answer, the issue was in the import of dehydrate like you mentioned I used autocomplete to import it and it picked the react-query version instead of query-core.

I am sorry, this is my fault for wasting your time. I suggest maybe adding some kind of warning to the docs about these two "identical" imports, so it's easier to find the issue faster.

Thank you again and sorry for me being not able to copy code :D

Not wasting our time at all. Really valuable feedback into improving DX of the docs. I think adding that kind of warning is a good idea. As you mentioned, most IDEs will autocomplete that line to use the wrong module, and it's very easy for our eyes to glaze over such a small detail.

@efilion
Copy link
Contributor Author

efilion commented Jan 16, 2023

@Ephem @efilion what would it take for us to get this from a draft PR to something that we can merge?

    • Drop dehydrate options
  • As @Ephem mentioned, compression mitigates some of the problems with sending duplicate data to the client. I don't think this is a detail that needs to be added to the docs, but this issue may be a worthwhile consideration for future versions of the library.
  • I will make this change shortly.
    • Make layout.jsx more consistent with create-next-app template
  • I will make this change shortly.
    • Mention that v4 targets a fix for having to re-export <Hydrate> simply to add use client
  • Waiting for confirmation on this. Alternatively, we can opt not mention anything in the docs at the present time.
    • Add a note on importing from react-query vs query-core
  • I will make this change shortly.
    • Further investigation/testing into the behaviour of Suspense and other concurrent features
  • I think this can be made optional for now by stressing in the Suspense section that support for such is still experimental. Maybe add a prompt to create an issue if unexpected behaviour is encountered.

I think we have a PR that adds a lot of utility as is, so I would suggest merging it after todos 1-4 are completed. Any refinements based on todo 5 could be addressed in a later PR.

@TkDodo
Copy link
Collaborator

TkDodo commented Jan 20, 2023

Waiting for confirmation on this. Alternatively, we can opt not mention anything in the docs at the present time.

We have a PR that adds useClient everywhere where we use state, context or effects:

I think the PR is good to go, but if you want to give it a review, please do. Would this solve the problem?

I think this can be made optional for now by stressing in the Suspense section that support for such is still experimental.

👍

@Ephem
Copy link
Collaborator

Ephem commented Jan 20, 2023

I think we can land #4738 first, I think it needs some changes but should be pretty quick?

So if you want to modify this to remove the HydrateOnClient-wrapper, feel free to! When the above PR has landed, we might want to note the exact version in these docs? I'm totally fine with merging these docs first and changing that later too though. 😄

@Ephem
Copy link
Collaborator

Ephem commented Jan 24, 2023

I took the liberty to push some changes to this, I hope that was okay.

  • Removed HydrateOnClient in favour of Hydrate (that PR is ready to be merged now`
  • Rewrote the Suspense-section
  • Some minor tweaks, including removing the note about importing directly from the core package since I'm not sure that still applies after we merge the 'use client' PR
  • Prettier
  • main had new docs on integrating with Remix, so I moved this whole section down to below those (since this is beta stuff) and added a note to the Next-section

I think with those changes this should be ready to merge after #4738 (update: now merged!), but I'd love it if someone could take a quick look. 😄 Great work on this @efilion!

@Ephem Ephem marked this pull request as ready for review January 24, 2023 10:57
Copy link
Collaborator

@TkDodo TkDodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow this is really good 👍

@efilion
Copy link
Contributor Author

efilion commented Jan 24, 2023

Suspense section is very well put. Thanks for taking care of that! Thrilled to see this PR get shipped :)

@TkDodo TkDodo merged commit b9cb5f1 into TanStack:main Jan 25, 2023
@hakankaan
Copy link

image

Hi. I'm trying to use Hydrate on server components but getting this error. Used HydrateOnClient component under QueryClient. Wrapped HydrateOnClient with another component and used at app/layout.tsx. I'm trying to achieve auth mechanism for routes. Can you guide me please?

image

@StringKe
Copy link

image

Hi. I'm trying to use Hydrate on server components but getting this error. Used HydrateOnClient component under QueryClient. Wrapped HydrateOnClient with another component and used at app/layout.tsx. I'm trying to achieve auth mechanism for routes. Can you guide me please?
image

I encountered the same problem, did you solve it?

@Ephem
Copy link
Collaborator

Ephem commented Mar 15, 2023

There's an issue to track this here, which includes a work around: #4933

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.