T
TanStack10mo ago
inland-turquoise

This Suspense boundary received an update before it finished hydrating.

Probably a more general SSR question. I see a race (I call it that because if I throttle my network it goes away) that causes
Uncaught Error: This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.
Uncaught Error: This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.
when I add Clerk to the React Query Start example. Here are some small repros, seems like something with about the ClerkProvider modifying state internally during hydration, which could be fine — just trying to figure out if it's expected. https://github.com/thomasballinger/tanstack-start-react-query-clerk-repro/pull/2 https://github.com/thomasballinger/tanstack-start-react-query-clerk-repro/pull/1 I think I'm looking for guidance on how bad this is and whether it's something to report to Clerk. I found this when using useSuspenseQuery with Convex and the TanStack Query with TanStack Start, but narrowed it down to just useSuspenseQuery and Clerk.
No description
9 Replies
flat-fuchsia
flat-fuchsia10mo ago
hey, we are facing the same issue, clerk breaks a few things in react apps, sadly they don't really care we are currently planning to migrate off clerk 💀
inland-turquoise
inland-turquoiseOP10mo ago
I'm wondering if this is about how they do state inside their client. If this doesn't happen all the time it's not the end of the world, it sounds like this warnings will be removed at some point in the future from React? I'm a big Clerk fan so this won't be enough to put me off, will poke around.
like-gold
like-gold10mo ago
Hey @ballingt and @tom. Just wanted to let you know that we (Clerk) are looking into this. Please give us a little bit to investigate. Also as this thread isn't in our normal channels please feel free o ping me mid nexst week if you haven't heard from us.
flat-fuchsia
flat-fuchsia10mo ago
awesome, thank you! let me know if we can help. running tanstack + clerk in prod for a few weeks now
inland-turquoise
inland-turquoiseOP10mo ago
playing around with arbitrary components replacing the Clerk one, I'm guessing the aim is to avoid any setState calls while hydration is taking place? And that if hydration takes too long this overlap is more likely? I still don't quite understand what the error is about. Oh it's not just while the root is hydrating, should have been obvious, it's just while the component is part of a suspended subtree (and this whole streaming+hydrating process is called hydrating)
inland-turquoise
inland-turquoiseOP10mo ago
As long as my setState() update comes after the big "Injected From Server" log it's fine
No description
inland-turquoise
inland-turquoiseOP10mo ago
but that's much later than a useSyncExternalStore reports hydration is done
inland-turquoise
inland-turquoiseOP10mo ago
No description
No description
inland-turquoise
inland-turquoiseOP10mo ago
so there's some notion of hydration that is different than what useSyncExternalStore reports (see https://tkdodo.eu/blog/avoiding-hydration-mismatches-with-use-sync-external-store for more on that, @TkDodo 🔮 helpful as usual) Is this a difference between the hydration of the initially rendered component tree and the tree that's streamed in later? And I need to detect that the streamed in bit is done? I could set an arbitrary timer like "wait for 10 seconds before doing anything dynamic," assuming that should be plenty to wait. But I'm not clear what I'm waiting for. It also only seems to be an issue if I modify a context in a provider, although it doesn't matter if that context is being used in the subtree (which makes sense, React doesn't use granular subscriptions on context) so @royanger possibly useful summary: - I think this is happening because of a Provider component changing the context value it provides before some subtree of it has streamed in and hydrated - I have no idea how to detect whether all subtrees are done streaming in - I wonder if waiting some configurable amount of time makes sense, using the server-provided auth credentials in the meantime I'm generally still getting used to this world of different parts of the app streaming in at different times from suspense boundaries, such that it's hard to reason about my app globally. I'd like to have global state (e.g. React Query) driving updates to components but it seems like I can't safely do that until a component has streamed in. I can write hooks that detect when they the component where they live is done hydrating, but Contexts are not so selective. This makes Context less useful for propagating changes, e.g. I wonder if a solution for Clerk here would be to avoid every mutating the context and instead just provide a consistent reference to an object containing methods to use. I wonder about going context-less for this: if properties of a useful auth context like isLoggedIn can't be modified, then they ought to be subscribed to outside of React, like another React Query queryFn. But that doesn't sound like it will mess well with the ecosystem, surely there are lots of <FooProvider> components that won't abide by this. Opened https://github.com/TanStack/router/discussions/2764 to discuss more, I think this is something folks here have thought about a lot more than I have. Updated there, I think this is an OK thing. Doesn't seem like it necessarily needs any changes, but we should confirm that and document it.

Did you find this page helpful?