-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
1 parent
4291b1c
commit 21d6716
Showing
7 changed files
with
75 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@astrojs/react': patch | ||
--- | ||
|
||
Fixes client hydration in islands when using experimentalReactChildren |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
packages/integrations/react/test/fixtures/react-component/src/components/WithChildren.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |