From 8d1be11320c93e5dbf5c44567c654d7d83f64b26 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 19 Dec 2025 10:42:29 -0800 Subject: [PATCH 1/2] fix: patch additional methods so React doesnt break with template elements fixes https://github.com/adobe/react-spectrum/issues/9376 --- .../@react-aria/collections/src/Hidden.tsx | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/packages/@react-aria/collections/src/Hidden.tsx b/packages/@react-aria/collections/src/Hidden.tsx index b6f2fa46607..e81ce9f9049 100644 --- a/packages/@react-aria/collections/src/Hidden.tsx +++ b/packages/@react-aria/collections/src/Hidden.tsx @@ -17,9 +17,14 @@ import React, {Context, createContext, forwardRef, JSX, ReactElement, ReactNode, // It will throw an error during hydration when it expects the firstChild to contain content rendered // on the server, when in reality, the browser will have placed this inside the `content` document fragment. // This monkey patches the firstChild property for our special hidden template elements to work around this error. +// does the same for appendChild/removeChild/insertBefore as per the issue below // See https://github.com/facebook/react/issues/19932 if (typeof HTMLTemplateElement !== 'undefined') { const getFirstChild = Object.getOwnPropertyDescriptor(Node.prototype, 'firstChild')!.get!; + const originalAppendChild = Object.getOwnPropertyDescriptor(Node.prototype, 'appendChild')!.value!; + const originalRemoveChild = Object.getOwnPropertyDescriptor(Node.prototype, 'removeChild')!.value!; + const originalInsertBefore = Object.getOwnPropertyDescriptor(Node.prototype, 'insertBefore')!.value!; + Object.defineProperty(HTMLTemplateElement.prototype, 'firstChild', { configurable: true, enumerable: true, @@ -31,6 +36,42 @@ if (typeof HTMLTemplateElement !== 'undefined') { } } }); + + Object.defineProperty(HTMLTemplateElement.prototype, 'appendChild', { + configurable: true, + enumerable: true, + value: function (node) { + if (this.dataset.reactAriaHidden) { + return this.content.appendChild(node); + } else { + return originalAppendChild.call(this, node); + } + } + }); + + Object.defineProperty(HTMLTemplateElement.prototype, 'removeChild', { + configurable: true, + enumerable: true, + value: function (node) { + if (this.dataset.reactAriaHidden) { + return this.content.removeChild(node); + } else { + return originalRemoveChild.call(this, node); + } + } + }); + + Object.defineProperty(HTMLTemplateElement.prototype, 'insertBefore', { + configurable: true, + enumerable: true, + value: function (node, child) { + if (this.dataset.reactAriaHidden) { + return this.content.insertBefore(node, child); + } else { + return originalInsertBefore.call(this, node, child); + } + } + }); } export const HiddenContext: Context = createContext(false); From 33926e7238d7d86d8449d5dc50f2d29994229502 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 22 Dec 2025 15:22:32 -0800 Subject: [PATCH 2/2] fix case where user navigates to Picker page from another page --- packages/@react-aria/collections/src/Hidden.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/@react-aria/collections/src/Hidden.tsx b/packages/@react-aria/collections/src/Hidden.tsx index e81ce9f9049..99a9e91e68a 100644 --- a/packages/@react-aria/collections/src/Hidden.tsx +++ b/packages/@react-aria/collections/src/Hidden.tsx @@ -66,6 +66,10 @@ if (typeof HTMLTemplateElement !== 'undefined') { enumerable: true, value: function (node, child) { if (this.dataset.reactAriaHidden) { + // child might not exist in this.content for some reason (stale?), add to end instead + if (child && !this.content.contains(child)) { + return this.content.appendChild(node); + } return this.content.insertBefore(node, child); } else { return originalInsertBefore.call(this, node, child);