react: [React 18] Selective Hydration fails hydration when using context api
Based on the selective hydration example provided by @gaearon ??
https://codesandbox.io/s/mystifying-haibt-39oed
Look out for 👉

One can see that hydrating html does in fact fail when using Context API — or perhaps that’s a red herring? The trees do in fact line up during render, and hydration, there’s just an effect that sets state — but that is post hydration??
Could be them related; in anycase — strictly speaking to that code sandbox, what am i doing wrongly?
Initially caught when ImportedComponent fails see https://github.com/theKashey/react-imported-component/blob/c290d76623693389a11cc514c92f47efadac47ba/src/ui/ImportedController.tsx#L29
About this issue
- Original URL
- State: open
- Created 3 years ago
- Comments: 20 (7 by maintainers)
When you don’t use Context, the trick is to use memo or useMemo.
e.g.
That way we know it hasn’t changed. Context is brute force because we don’t know if something below reads it.
(paint)
The general model here is that code is expected to load relatively quickly and that you eagerly hydrate the whole page on idle.
This makes it so that you typically won’t hit the scenario of hiding existing content. Since you’ll have downloaded everything by the time the user interacts with the page.
The exception is things that update immediately and synchronously without user interaction - which is bad practice for other reasons already.
The other exception when this can become a problem is when you don’t subscribe to the eager hydration model. Eg if you only want to even start downloading the code upon interaction. That’s a very different model than what we’ve designed for, so it requires a different design. That’s the case where I suggest splitting into multiple roots.
Another case if you do clever stuff by inferring that hydration is going on but I think it’s fair that you have to spend some time updating those libraries when the hydration model has drastically changed. It’s likely to break anyway since the assumptions have changed.
In other cases this wouldn’t be an issue.
That sounds like a really complication for any existing applications, which can be summarised as “use a self contained state management solution, some of them will work, not low level system primitives”
Multiple roots are falling into the same bucket, as every such root should be wrapped with all required providers with common state or synchronised, or exists outside or React.
For quite a while the overall diffraction was to put more stuff “in”, so asking to put some “out” is not an option as it requires some sort of shotgun surgery for many third party dependencies
The way around it is to not use React for tracking the updates. You can use a subscription (possibly with useSyncExternalStore).
If you want deep advanced control over how parts of a page is hydrated, you’re better off splitting up into multiple roots. Like is already possible. It’s going to interplay with other features in subtle ways anyway that you’ll need to resolve.
If I read correctly - there is no way to keep areas suspended with context updates, many of them can have just “not-UI” nature, like hydration/loading state to power phased code splitting (
importForInteractions)Can I ask to provide more control over this to the user space, as I am more than capable to invalidate my caches and can understand when I need suspended fragment to be hydrated. More of it - probably in this case I need it to be actually “hydrated”, ie want hydration process to continue, not destroy existing tree and display fallback.
As I understand - any context update invalidates all dehydrated
SuspenseComponents. Not sure is it a feature or a bug, and is there any extra flag on Suspense to control this behavior.