Skip to content

SCAL-336321 Skip the pre-render home hop when a new embed shows an equal config - #689

Closed
sastaachar wants to merge 1 commit into
mainfrom
SCAL-336321-react-remount
Closed

sastaachar wants to merge 1 commit into
mainfrom
SCAL-336321-react-remount

Conversation

@sastaachar

Copy link
Copy Markdown
Contributor

Problem

LiveboardEmbed.beforePrerenderVisible() (from #659) routes via home when the pre-render is already on the same liveboard route. That clears state left over from a previous config. It skips the hop only when previous === this.

React constructs a new LiveboardEmbed on every mount, so the check never matches there. Every remount of an unchanged <PreRenderedLiveboardEmbed> goes home and reloads the warm liveboard.

Change

A hide/show is now detected by config, not identity. isSameEmbedConfig compares previous.viewConfig with this.viewConfig and treats callbacks as equal, since React passes a fresh closure each render. The hop still fires on the same route when the config differs (for example other runtimeFilters).

Version bumped to 1.52.2-beta.1.

Testing

  • New: a new instance with an equal config does not hop. It fails without the fix.
  • New: a new instance on the same route with different filters still hops.
  • Full suite: 50/50 suites, 2013 passed.

SCAL-336321

…ual config

React constructs a new LiveboardEmbed on every mount, so the previous === this
check never matched and every remount of an unchanged pre-rendered liveboard
routed via home and reloaded. Compare viewConfig instead, treating callbacks
as equal.

SCAL-336321
@sastaachar
sastaachar requested a review from a team as a code owner September 28, 2026 16:40

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a configuration comparison check in LiveboardEmbed to prevent routing via home when a new instance shares an identical configuration with the previous one, and adds corresponding unit tests. Feedback on the implementation highlights a potential performance and recursion issue where lodash/isEqualWith might deeply compare massive, circular DOM elements inside viewConfig. It is recommended to update the customizer to compare Node instances by identity to avoid blocking the UI thread or exceeding the call stack limit.

Comment thread src/embed/liveboard.ts
Comment on lines +1047 to +1056
// Callbacks are compared as equal: React passes a fresh closure per render.
private isSameEmbedConfig(previous?: LiveboardEmbed): boolean {
if (!previous) return false;
if (previous === this) return true;
return isEqualWith(
previous.viewConfig,
this.viewConfig,
(a, b) => (typeof a === 'function' && typeof b === 'function' ? true : undefined),
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The viewConfig object can contain references to DOM elements (such as preRenderContainer or containerSelector in preRenderConfig which can be HTMLElement / Node instances). When isEqualWith recursively compares viewConfig, it will attempt to deeply compare these DOM elements. Since DOM elements are massive, circular, and complex objects, deeply comparing them is extremely slow, can cause significant performance degradation (UI thread blocking), or even crash the application with a Maximum call stack size exceeded error due to deep recursion.

To prevent this, we should update the customizer to check if the values are instances of Node and compare them by identity (a === b).

    // Callbacks are compared as equal: React passes a fresh closure per render.
    private isSameEmbedConfig(previous?: LiveboardEmbed): boolean {
        if (!previous) return false;
        if (previous === this) return true;
        return isEqualWith(
            previous.viewConfig,
            this.viewConfig,
            (a, b) => {
                if (typeof a === 'function' && typeof b === 'function') {
                    return true;
                }
                if (a instanceof Node && b instanceof Node) {
                    return a === b;
                }
                return undefined;
            },
        );
    }

@sastaachar

Copy link
Copy Markdown
Contributor Author

Moved into #684 (commit 927382e).

@sastaachar sastaachar closed this Sep 28, 2026
@sastaachar
sastaachar deleted the SCAL-336321-react-remount branch September 28, 2026 18:37
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.

1 participant