Skip to content

fix(react): pass only componentName and uid to ErrorBoundary - #624

Open
gregorjan wants to merge 3 commits into
Sitecore:devfrom
gregorjan:feature/error-boundary-rendering-payload
Open

gregorjan wants to merge 3 commits into
Sitecore:devfrom
gregorjan:feature/error-boundary-rendering-payload

Conversation

@gregorjan

Copy link
Copy Markdown

Problem

AppPlaceholder wraps every rendering it renders in ErrorBoundary:

// packages/react/src/components/Placeholder/AppPlaceholder.tsx
<ErrorBoundary
  ...
  rendering={rendered.props.rendering as ComponentRendering}
>

ErrorBoundary is a client component ('use client'), so every prop it receives is serialized into the RSC flight payload of the page — inline in the HTML and again in the .rsc artifact. It reads exactly two fields off rendering:

// packages/react/src/components/ErrorBoundary.tsx
console.error(`An error occurred in component ${this.props.rendering?.componentName} (${this.props.rendering?.uid}): `)
...
React.createElement('em', null, this.props.rendering?.componentName)

The object it is given carries fields (the component's resolved datasource) and placeholders (its whole nested subtree). For a server component that has already rendered that content to HTML, the same content is shipped a second time as JSON so that, if the component throws, a message can name it.

Measured on one page of a production site (header + footer from Sitecore partial designs):

rendering passed to ErrorBoundary read by ErrorBoundary
Footer 20,896 B 71 B
Header 36,613 B ~70 B

Fix

Narrow the rendering to the two fields before passing it. ComponentRendering requires only componentName, so this needs no type or public-API change.

Result

Same page, production build, before → after:

html    302,029 -> 266,079   -35,950  (-11.9%)
rsc     215,348 -> 183,802   -31,546  (-14.6%)
total   517,377 -> 449,881   -67,496  (-13.0%)

Rendered output is byte-identical: same text, same 162 <a href> values. Datasource markers drop out of the payload ("datasource" 5 → 0, GUIDs 54 → 15). For an ISR-cached site this is per stored page, so it multiplies by page count.

The same code is present in 1.4.1, 2.4.0 and the current 3.0 canary.

Notes

  • Added a unit test asserting the boundary receives only componentName and uid.
  • eslint passes on both changed files. I could not run the package's mocha suite locally — test/setup.js registers ts-node/register/transpile-only but the specs load as ESM in my environment (ERR_UNKNOWN_FILE_EXTENSION for .tsx, ERR_MODULE_NOT_FOUND for extensionless imports), which reproduces on dev without my changes. Relying on CI for the suite; happy to adjust if it flags anything.
  • Placeholder.tsx (the non-RSC placeholder) passes the rendering the same way. Its children are already client-side so the payload impact differs; left alone here to keep the change focused — glad to include it if you prefer.

Opened as a draft for your review of the approach.

@changeset-bot

changeset-bot Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: eca5c9d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sitecore-content-sdk/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gregorjan
gregorjan force-pushed the feature/error-boundary-rendering-payload branch from c0fd2ce to 976f874 Compare September 15, 2026 07:52
@gregorjan
gregorjan marked this pull request as ready for review September 15, 2026 07:55
@art-alexeyenko

Copy link
Copy Markdown
Collaborator

@gregorjan that would be a sweet thing to do, thanks for the proposal.
Could you please doublecheck the test, as it fails with an error

  1. App Placeholder logic
    AppPlaceholder BYOC fallback
    should pass only componentName and uid of the rendering to ErrorBoundary:
    TypeError: Cannot read properties of null (reading 'placeholders')
    at Context. (src/components/Placeholder/AppPlaceholder.test.tsx:558:67)
    at processImmediate (node:internal/timers:574:21)

You could try running yarn install for the monorepo, with no samples present and run npm run test within react package to test things locally.

Jan Gregor and others added 2 commits October 2, 2026 09:37
ErrorBoundary is a client component, so the full ComponentRendering it received
was serialized into the RSC payload of every page - including each component's
resolved datasource, fields and nested placeholders, for server components that
had already rendered them to HTML. ErrorBoundary only displays componentName and
uid, so narrow the rendering before passing it.
@gregorjan
gregorjan force-pushed the feature/error-boundary-rendering-payload branch from 5a2b409 to 0ed7a62 Compare October 2, 2026 07:44
@gregorjan

Copy link
Copy Markdown
Author

@art-alexeyenko
Thanks! Fixed in 0ed7a62: the test was missing page.layout = byocWrapperData (so route was null), and it asserted on the outer placeholder ErrorBoundary call instead of the per-component ones. Rebased on latest dev; yarn test-packages passes locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants