Skip to content

Commit

Permalink
fix(react): make children undefined with experimentalReactChildren (
Browse files Browse the repository at this point in the history
#9141)

* add test script

* make children `undefined` with self-closing tags

* add changeset

* refactor: simplify
  • Loading branch information
lilnasy authored Nov 21, 2023
1 parent d9e72ce commit af43fb5
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/three-timers-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/react': patch
---

Fixes an issue where slotting self-closing elements (img, br, hr) into react components with `experimentalReactChildren` enabled led to an error.
6 changes: 4 additions & 2 deletions packages/integrations/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"scripts": {
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
"build:ci": "astro-scripts build \"src/**/*.ts\"",
"dev": "astro-scripts dev \"src/**/*.ts\""
"dev": "astro-scripts dev \"src/**/*.ts\"",
"test": "mocha --exit --timeout 20000"
},
"dependencies": {
"@vitejs/plugin-react": "^4.0.4",
Expand All @@ -57,7 +58,8 @@
"cheerio": "1.0.0-rc.12",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"vite": "^4.4.9"
"vite": "^4.4.9",
"mocha": "^10.2.0"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",
Expand Down
15 changes: 15 additions & 0 deletions packages/integrations/react/test/parsed-react-children.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect } from 'chai';
import convert from "../vnode-children.js";

describe('experimental react children', () => {
it('has undefined as children for direct children', () => {
const [ imgVNode ] = convert('<img src="abc"></img>');
expect(imgVNode.props).to.deep.include({ children: undefined });
})

it('has undefined as children for nested children', () => {
const [ divVNode ] = convert('<div><img src="xyz"></img></div>');
const [ imgVNode ] = divVNode.props.children;
expect(imgVNode.props).to.deep.include({ children: undefined });
})
})
16 changes: 6 additions & 10 deletions packages/integrations/react/vnode-children.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,20 @@ export default function convert(children) {
let key = 0;

function createReactElementFromNode(node) {
const childVnodes = Array.isArray(node.children)
const childVnodes = Array.isArray(node.children) && node.children.length
? 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)
.map((child) => createReactElementFromNode(child))
.filter(Boolean)
: 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);
} else if (node.type === TEXT_NODE) {
// 0-length text gets omitted in JSX
return node.value.trim() ? node.value : undefined;
}
}

Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit af43fb5

Please sign in to comment.