summaryrefslogtreecommitdiff
path: root/packages/integrations/react/vnode-children.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/vnode-children.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/vnode-children.js')
-rw-r--r--packages/integrations/react/vnode-children.js39
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;
}