Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sitecore-jss-react][sitecore-jss-nextjs] Prevent hydration error with dynamic components #1807

Merged
merged 6 commits into from
Jun 3, 2024

Conversation

art-alexeyenko
Copy link
Contributor

@art-alexeyenko art-alexeyenko commented May 31, 2024

  • This PR follows the Contribution Guide
  • Changelog updated - TBA
  • Upgrade guide entry added

Description / Motivation

Fixes hydration issues when ErrorBoundary's Suspense wraps nextjs's dynamic() wrapper.
dynamic() components will have a render prop. If it's present - the component will not be wrapped in ErrorBoundary's Suspense preventing intermittent hydration problems.

Testing Details

  • Unit Test Added
  • Manual Test/Other (Please elaborate) - Errors are successfully captured in connected mode

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Comment on lines 276 to 291
const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
if (!isEmpty) {
rendered = (
<ErrorBoundary
key={rendered.type + '-' + index}
errorComponent={this.props.errorComponent}
componentLoadingMessage={this.props.componentLoadingMessage}
type={type}
isDynamic={(component as JssComponentType).isDynamic}
{...rendered.props}
>
{rendered}
</ErrorBoundary>
);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with this refactor does this mean PlaceholderMetadata component would not be included in the ErrorBoundary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The main goal of ErrorBoundary is to alert to problems with customer's and app's components. With this change the focus is moved on these components specifically and our built-in stuff will not affect error boundaries.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but what if an error occurs in the PlaceholderMetadata component?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we have a larger problem on our side and each page of the site stops working in editing mode.
Which would be roughly the same behavior if PlaceholderMetadata errors are handled by ErrorBoundary - the content will not be shown.

@art-alexeyenko art-alexeyenko requested a review from a team May 31, 2024 22:16
it('should not render Suspense and default loading message when wrapping a dynamic component', async () => {
// mount fails with lazy component and no suspense
const rendered = mount(
<Suspense>
Copy link
Contributor

@addy-pathania addy-pathania Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we have to wrap all the dynamic components with Suspense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for tests, yes
mount here refers to enzyme mount() specifically

Copy link
Contributor

@addy-pathania addy-pathania left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

@addy-pathania addy-pathania merged commit 5a3dd9c into dev Jun 3, 2024
1 check passed
@addy-pathania addy-pathania deleted the bug/jss-3363-hydration-error-dynamics branch June 3, 2024 21:00
component as React.ComponentType,
this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps
);

const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
if (!isEmpty) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@art-alexeyenko Previously we had some comments here explaining problems, it should be reverted back

component as React.ComponentType,
this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps
);

const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@art-alexeyenko Should be added under if statement

@@ -5,3 +5,11 @@ import { ComponentType } from 'react';
* @param {string?} exportName component to be imported in case you export multiple components from the same file
*/
export type ComponentFactory = (componentName: string, exportName?: string) => ComponentType | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@art-alexeyenko Here ComponentFactory returns ComponentType while you introduced a new JssComponentType. Here is a mismatch from my understanding

component as React.ComponentType,
this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps
);

const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
if (!isEmpty) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@art-alexeyenko Add a comment here explaining that components are not wrapped in Chromes Edit Mode

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.

3 participants