diff --git a/flow-react/src/main/resources/com/vaadin/flow/server/frontend/ReactAdapter.template b/flow-react/src/main/resources/com/vaadin/flow/server/frontend/ReactAdapter.template index f1ce4af0874..f1ed2033417 100644 --- a/flow-react/src/main/resources/com/vaadin/flow/server/frontend/ReactAdapter.template +++ b/flow-react/src/main/resources/com/vaadin/flow/server/frontend/ReactAdapter.template @@ -139,6 +139,8 @@ export abstract class ReactAdapterElement extends HTMLElement { #unmountComplete = Promise.resolve(); + #portalOutlet: HTMLElement | null = null; + constructor() { super(); this.#renderHooks = { @@ -151,9 +153,14 @@ export abstract class ReactAdapterElement extends HTMLElement { } public async connectedCallback() { + if (this.#portalOutlet === null) { + this.#portalOutlet = document.createElement('flow-portal-outlet'); + this.#portalOutlet.style.display = 'contents'; + this.appendChild(this.#portalOutlet); + } await this.#unmountComplete; this.#rendering = createElement(this.#Wrapper); - const createNewRoot = this.dispatchEvent(new CustomEvent('flow-portal-add', { + const createNewRoot = this.#portalOutlet!.dispatchEvent(new CustomEvent('flow-portal-add', { bubbles: true, cancelable: true, composed: true, @@ -167,7 +174,7 @@ export abstract class ReactAdapterElement extends HTMLElement { return; } - this.#root = createRoot(this); + this.#root = createRoot(this.#portalOutlet!); this.#maybeRenderRoot(); this.#root.render(this.#rendering); } @@ -187,7 +194,7 @@ export abstract class ReactAdapterElement extends HTMLElement { } public async disconnectedCallback() { - this.dispatchEvent(new CustomEvent('flow-portal-remove', { + this.#portalOutlet!.dispatchEvent(new CustomEvent('flow-portal-remove', { bubbles: true, cancelable: true, composed: true,