adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.54k stars 1.08k forks source link

React Suspense components wrapped in Provider emit runtime errors when using SSR #6728

Open russell-mckenzie opened 1 month ago

russell-mckenzie commented 1 month ago

Provide a general summary of the issue here

We've encountered an unexpected runtime error while attempting to server-side render <Suspense> lazy-loaded components using Next.js.

πŸ€” Expected Behavior?

When using a React <Suspense> component inside a <Provider>, there should be no runtime error emitted and the boundary should not switch to client rendering.

😯 Current Behavior

The browser displays the following error message when the <Suspense> component is rendered.

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.

We receive this error consistently if the <Suspense> component is mounted inside a React Spectrum 3 <Provider> irrespective of the prop values provided.

πŸ’ Possible Solution

My theory is that this is related to hooks like useMediaQuery() which are used in the Provider and implicitly cause an update client-side after or during hydration (but I'm not an expert here).

πŸ”¦ Context

No response

πŸ–₯️ Steps to Reproduce

I've prepared a minimal CodeSandbox to demonstrate the error: CodeSandbox Devbox. This sandbox has Next.js 14, with React Spectrum 3.35.1 and the next.config.js changes advised to enable CSS bundling with Next.js.

Simply open the Sandbox and navigate to /test (if not already displayed).

Version

3.35.1

What browsers are you seeing the problem on?

Firefox, Chrome, Safari, Microsoft Edge

If other, please specify.

No response

What operating system are you using?

macOS Sonoma

🧒 Your Company/Team

Adobe/Business Essentials

πŸ•· Tracking Issue

No response

snowystinger commented 1 month ago

useMediaQuery shouldn't be causing an issue, it's not doing anything that I would consider non-Reacty, updates are done after hydration. I could be missing something though.

Were you able to try any of the suggestions that are on threads about this error? What did you try and what were the results?

To debug this, I would start with a working SSR + lazy example, then start adding small parts from RSP Provider until it breaks. By that I mean pick a hook out of Provider and add that, not the entire Provider. Or add a context. Keep doing that until the problem is replicated. If you have a feeling it is useMediaQuery, then that's as good a place as any to start.

herkulano commented 3 weeks ago

I'm having this issue with Remix. I've isolated the problem to useLocale() or <I18nProvider locale="">. Using either triggers this error.

Using bootstrapScriptContent: getLocalizationScript(getLocale()), in entry.server.tsx works for the components without causing errors, but I can't use useLocale() as it triggers this error.

herkulano commented 3 weeks ago

Here's a reproduction: https://stackblitz.com/edit/remix-run-remix-gqbpjj?file=app%2Froutes%2F_index.tsx

The errors are only triggered on first run or when the page refreshes, otherwise it's not getting the SSR page.

snowystinger commented 3 weeks ago

Given that the page loads, are we sure that this isn't a false error? https://www.reddit.com/r/nextjs/comments/yxa87v/im_glad_im_not_the_only_one_that_thinks_this/

herkulano commented 3 weeks ago

No idea, but it's been 2 years already, maybe they changed their minds or is the PR still open after this long? I'm also checking for console.error() in e2e tests. I can't take it to production with these errors.