Fix hydration of components inside <Suspense>
#2663
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a redo of #2633 but with a more targeted fix for just React 18+
Previously, when dealing with SSR, we had a hook that would basically force a re-render of all components on page load. This also used some global state so we didn't unnecessarily cause re-renders for components that were mounting after the page had already loaded.
However, because
<Suspense>
delays hydration this is no longer a viable solution. I've implemented a targeted fix by (mis)using theuseSyncExternalStore
API. You can provide agetServerSnapshot
callback that only runs on the server AND in the browser but only when hydrating. This gives us just enough info to know when hydration is happening.I've slotted that into our
useServerHandoffComplete()
hook to handle the<Suspense>
case. I'm also using wildcard imports, a"useSyncExternalStore" in React
guard, and a lazy closure to ensure that bundlers don't statically analyze this in a way that errors for React < 18.Fixes #2400