summaryrefslogtreecommitdiff
path: root/packages/integrations/react/client.js
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@skypack.dev> 2023-10-24 08:05:19 -0400
committerGravatar GitHub <noreply@github.com> 2023-10-24 08:05:19 -0400
commit4dee38711cbf83efb5e12fbfa8e69e2495c49acf (patch)
tree05de3ac83e729935ab72cd2ada07e03ddcb0c3d8 /packages/integrations/react/client.js
parent5dd1ed50b2f9428946b0b273e0ce8f13c19aa3b5 (diff)
downloadastro-4dee38711cbf83efb5e12fbfa8e69e2495c49acf.tar.gz
astro-4dee38711cbf83efb5e12fbfa8e69e2495c49acf.tar.zst
astro-4dee38711cbf83efb5e12fbfa8e69e2495c49acf.zip
Fix client hydration in experimentalReactChildren (#8898)
* Fix client hydration in experimentalReactChildren * Add tests * Add a changeset * Use recursion instead of walking * getChildren -> swap order --------- Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
Diffstat (limited to 'packages/integrations/react/client.js')
-rw-r--r--packages/integrations/react/client.js39
1 files changed, 38 insertions, 1 deletions
diff --git a/packages/integrations/react/client.js b/packages/integrations/react/client.js
index dbd32c0c5..73f43aa94 100644
--- a/packages/integrations/react/client.js
+++ b/packages/integrations/react/client.js
@@ -10,6 +10,42 @@ function isAlreadyHydrated(element) {
}
}
+function createReactElementFromDOMElement(element) {
+ let attrs = {};
+ for(const attr of element.attributes) {
+ attrs[attr.name] = attr.value;
+ }
+
+ return createElement(element.localName, attrs,
+ Array.from(element.childNodes).map(c => {
+ if(c.nodeType === Node.TEXT_NODE) {
+ return c.data;
+ } else if(c.nodeType === Node.ELEMENT_NODE) {
+ return createReactElementFromDOMElement(c)
+ } else {
+ return undefined;
+ }
+ }).filter(a => !!a)
+ );
+}
+
+function getChildren(childString, experimentalReactChildren) {
+ if(experimentalReactChildren && childString) {
+ let children = [];
+ let template = document.createElement('template');
+ template.innerHTML = childString;
+ for(let child of template.content.children) {
+ children.push(createReactElementFromDOMElement(child))
+ }
+ return children;
+ } else if(childString) {
+ return createElement(StaticHtml, { value: childString });
+ } else {
+ return undefined;
+ }
+
+}
+
export default (element) =>
(Component, props, { default: children, ...slotted }, { client }) => {
if (!element.hasAttribute('ssr')) return;
@@ -19,10 +55,11 @@ export default (element) =>
for (const [key, value] of Object.entries(slotted)) {
props[key] = createElement(StaticHtml, { value, name: key });
}
+
const componentEl = createElement(
Component,
props,
- children != null ? createElement(StaticHtml, { value: children }) : children
+ getChildren(children, element.hasAttribute('data-react-children'))
);
const rootKey = isAlreadyHydrated(element);
// HACK: delete internal react marker for nested components to suppress aggressive warnings