Sitecore / jss

Software development kit for JavaScript developers building web applications with Sitecore Experience Platform
https://jss.sitecore.com
Apache License 2.0
263 stars 275 forks source link

Suspense boundary error #1953

Closed thany closed 3 days ago

thany commented 1 month ago

Describe the Bug

Getting this error:

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.

It's intermittent. Seems totally random when it happens.

Most likely this one is the cause (annoyingly the error doesn't say which Suspense boundary it's complaining about):

image

We don't directly have a Suspense anywhere in our project.

To Reproduce

The cause for this error was added in JSS 22.1.0:

image

So update to that version, have a reasonably complex page, and F5 away.

How to reliably reproduce, I don't know. THat's part of the problem.

Expected Behavior

No error, things working as intended.

Possible Fix

Maybe this ErrorBoundary/Suspense thing should have gone through more rigorous testing.

Provide environment information

thany commented 1 month ago

I've been searching high and low to figure out the root cause.

I can randomly disable and enable the contents of placeholders, and it will still randomly give this error. I've searched the component tree and there are NO Lazy/Dynamic components anywhere - these are almost always given as being the culprits if you search for the error.

On top of that, we are NOT doing any form of clientside data fetching. Everything happens serverside, which happens before the SSR and hydration phases begin. And with this in mind, I just cannot fathom how a component could cause a change during the hydration phase. Like seriously, what sort of thing could possibly cause this?

On top of that again, the problem is super difficult to track down and to eliminate the culprit component. Because it's so damn random. I might disable a component and then the error doesn't happen for the next, say, 20 reloads. And then it does again. Or not. There is just no way to know.

If only I could reproduce this error WITHOUT using a Lazy/Dynamic component, then I could better understand wat JSS is trying to achieve with these suspenses.

I know this feature was listed as a breaking change. And ooh boy, it sure is one.

art-alexeyenko commented 1 month ago

HI @thany

I put this issue in our backlog for further investigation, thank you for reporting this. To better understand it, can you help me narrow down the problem?

  1. First, a sanity check. You mention your Sitecore version as 9.3. Is that a typo? Please note, JSS 22.1 is only compatible with XMCloud and Sitecore 10.4
  2. Can you prepare a minimal repro scenario? Perhaps a single component structure, or a sample page structure we can setup on our end and dig more?

then I could better understand wat JSS is trying to achieve with these suspenses

ErrorBoundaries are introduced as a way to limit react component errors to only the components themselves, without crashing the whole page. Previously you could get an empty page when a single component threw an error. Following this change, only an error message should display instead of the failing component. I hope this helps.

thany commented 4 weeks ago
  1. Not a typo. I haven't seen this as a breaking change in the changelog - did I overlook it? Should I stick at JSS 20.x? And then will you there be maintence releases on the 20.x branch for bug fixes and such?
  2. Minimal scenarios almost never trigger the issue. It's like complexity triggers it. It maybe needs to be "slow enough" whatever that means.

Edit: thinking about (1) a little more - I do find this hard to believe, since it appears to be a frontend-only issue. Nevertheless, JSS 20 doesn't have this blasted Suspense component in every Placeholder, making it impossible to crash on them.

I do find it exceedingly difficult to figure out what causes the problem. The error message is (to nobody's fault probably) extremely vague, and fails to provide even a hint to which Suspense is problematic, let alone which component is the likeliest culprit. The stack trace is near enough useless. So if you know of a solid way to diagnose a problem like this, I'd be happy to figure it out, but right now I'm blind-folded with my hands cuffed, so to speak.

And other thing I noticed is each Placeholder can be "dynamic". I don't know what that means, but I do know by looking at the JSS source code that it renders the content without a Suspense around it. Is that something worth looking into? Tbh, I'm not sure how a non-dynamic (static?) Placeholder needs a Suspense and a dynamic one doesn't - it feels like it should be the other way round, but then again, what do I know.

art-alexeyenko commented 4 weeks ago

Not a typo. I haven't seen this as a breaking change in the changelog - did I overlook it? Should I stick at JSS 20.x?

JSS versioning matches that of the Headless Services module on the Sitecore side - and each JSS version is made to be compatible with features of the corresponding module. As such JSS version 22 is only compatible with the module release for Sitecore 10.4. While later versions of JSS can potentially work with older Sitecore deployments, we cannot guarantee a smooth experience and errors are to be expected. You can check the the README to find info and links for the supported JSS setups. In the case of Sitecore 9.3 the compatible version is JSS 13.

And then will you there be maintence releases on the 20.x branch for bug fixes and such?

For the supportability, JSS support follows the timelines for Sitecore CMS version support, outlined here - so releases for 20.x and 21.x are still possible, but not for 13.x. It would be best to upgrade the Sitecore CMS version to both keep the support going and get the latest features that were introduced.

thany commented 4 weeks ago

JSS 20 works fine with Sitecore 9.3.

Why would you stick it to such an ancient version? This is also pinning other dependent packages like React, Nextjs, and many others. Why can't you make things backwards compatible? Surely JSS is little more than some Sitecore endpoints, and some magic around building up components to match what Sitecore returns. That components magic is pure frontend. What has Sitecore got to do with this?


Coming back to the problem at hand - do you actually know for sure that this problem is caused by the use of Sitecore 9? You can slap me on the wrist for using the "wrong" version, but is that actually the cause for sure?

illiakovalenko commented 3 days ago

@thany

JSS 20 works fine with Sitecore 9.3. Why would you stick it to such an ancient version? This is also pinning other dependent packages like React, Nextjs, and many others. Why can't you make things backwards compatible? Surely JSS is little more than some Sitecore endpoints, and some magic around building up components to match what Sitecore returns. That components magic is pure frontend. What has Sitecore got to do with this?

This is the rule of our product, we are not providing official support in case your version has a mismatch, since sometimes we are providing new features/breaking changes that are sticked to Sitecore version. There is no way to make all the things backwards compatible, since we are upgrading the frameworks / node.js / adding new features.

Coming back to the problem at hand - do you actually know for sure that this problem is caused by the use of Sitecore 9? You can slap me on the wrist for using the "wrong" version, but is that actually the cause for sure?

We can't say for sure since we don't have an exact scenario and we didn't receive any reports from other customers. The "ErrorBoundary" component provides console.logs and information about component, renderingId of the failed component. (in dev mode) Please, investigate more and provide us the steps to reproduce in order to be able to solve the problem if it's a bug. May be you are doing some extra stuff in your component that triggers extra re-render, update and it breaks the Placeholder. Also we don't know "react" version you are using. We need more information. I close this ticket for now. Feel free to open another issue after you collect more information