react: Bug: Streamed hydration hangs when consecutive Suspense boundaries suspend during streaming

When streaming from the server, I’ve encountered a bug where client-side hydration with hydrateRoot() will seemingly “pause” and never complete, leaving html tags with hidden and id attributes hanging around. Any user events cause this error to show, likely because the app still thinks it’s in the middle of hydrating. Interestingly enough, if you switch the promise timeouts in routeConfig so that post resolves earlier than posts, then you will not have this issue. So to summarize for this example: if only one boundary suspends, all is well, but if two boundaries suspend, we see this bug.

Hoping this is something stupid on my part, but stuck nonetheless.

React version: 18.2.0

Steps To Reproduce

  1. Load the example at https://stackblitz.com/github/tanstack/router/tree/beta/examples/react/basic-ssr?file=src%2FApp.tsx
  2. Paste /posts/1 into the preview URL to trigger a server-side load of that full URL
  3. Inspect the dom

Link to code example:

https://stackblitz.com/github/tanstack/router/tree/beta/examples/react/basic-ssr?file=src%2FApp.tsx

The current behavior

The markup is not visible (some of it is hidden)

The expected behavior

All of the markup should be visible

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 15 (1 by maintainers)

Most upvoted comments

https://github.com/facebook/react/issues/25710#issuecomment-1321470216 Works fine and as expected. So now I’m trying to find the differences between the two.

I trust me I know the pain. I’ll improve the material as I can.

Tanner Linsley On Nov 19, 2022 at 8:53 AM -0700, dan @.***>, wrote:

Yea, I just mean that if there’s a smaller example then (even if the issue is with the pattern) I’d be able to tell why. In fact just copy pasting the library into the sandbox so that we can start narrowing it down would be helpful. The issue is just that since it’s on npm, it’s impossible to work by removing pieces and seeing what’s essential to the problem. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

This worked

export const routeConfig = createRouteConfig().addChildren([
  postRoute,
  indexRoute,
]);

Maybe the issue is related to @tanstack/react-router

This only triggers one suspense boundary. So that’s expected.