diff options
author | 2023-10-24 08:05:19 -0400 | |
---|---|---|
committer | 2023-10-24 08:05:19 -0400 | |
commit | 4dee38711cbf83efb5e12fbfa8e69e2495c49acf (patch) | |
tree | 05de3ac83e729935ab72cd2ada07e03ddcb0c3d8 /packages/integrations/react/client.js | |
parent | 5dd1ed50b2f9428946b0b273e0ce8f13c19aa3b5 (diff) | |
download | astro-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.js | 39 |
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 |