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/vnode-children.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/vnode-children.js')
-rw-r--r-- | packages/integrations/react/vnode-children.js | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/packages/integrations/react/vnode-children.js b/packages/integrations/react/vnode-children.js index ea5bc0869..57a7fb66f 100644 --- a/packages/integrations/react/vnode-children.js +++ b/packages/integrations/react/vnode-children.js @@ -1,35 +1,30 @@ -import { parse, walkSync, DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE } from 'ultrahtml'; +import { parse, DOCUMENT_NODE, ELEMENT_NODE, TEXT_NODE } from 'ultrahtml'; import { createElement, Fragment } from 'react'; let ids = 0; export default function convert(children) { - const nodeMap = new WeakMap(); let doc = parse(children.toString().trim()); let id = ids++; let key = 0; - let root = createElement(Fragment, { children: [] }); - walkSync(doc, (node, parent, index) => { - let newNode = {}; - if (node.type === DOCUMENT_NODE) { - nodeMap.set(node, root); - } else if (node.type === ELEMENT_NODE) { - const { class: className, ...props } = node.attributes; - // NOTE: do not manually pass `children`, React handles this internally - newNode = createElement(node.name, { ...props, className, key: `${id}-${key++}` }); - nodeMap.set(node, newNode); - if (parent) { - const newParent = nodeMap.get(parent); - newParent.props.children[index] = newNode; - } - } else if (node.type === TEXT_NODE) { - newNode = node.value; - if (newNode.trim() && parent) { - const newParent = nodeMap.get(parent); - newParent.props.children[index] = newNode; + function createReactElementFromNode(node) { + const childVnodes = Array.isArray(node.children) ? node.children.map(child => { + if(child.type === ELEMENT_NODE) { + return createReactElementFromNode(child); + } else if(child.type === TEXT_NODE) { + // 0-length text gets omitted in JSX + return child.value.trim() ? child.value : undefined; } + }).filter(n => !!n) : undefined; + + if(node.type === DOCUMENT_NODE) { + return createElement(Fragment, {}, childVnodes); + } else if(node.type === ELEMENT_NODE) { + const { class: className, ...props } = node.attributes; + return createElement(node.name, { ...props, className, key: `${id}-${key++}` }, childVnodes); } - }); + } + const root = createReactElementFromNode(doc); return root.props.children; } |