diff --git a/.changeset/fresh-eels-speak.md b/.changeset/fresh-eels-speak.md new file mode 100644 index 000000000000..d826bb516b18 --- /dev/null +++ b/.changeset/fresh-eels-speak.md @@ -0,0 +1,5 @@ +--- +'@astrojs/react': patch +--- + +Support passing `children` as props to a React component diff --git a/packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx b/packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx new file mode 100644 index 000000000000..cdcb0e0a6d79 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/WithChildren.jsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function ({ children }) { + return
{children}
; +} diff --git a/packages/astro/test/fixtures/react-component/src/pages/index.astro b/packages/astro/test/fixtures/react-component/src/pages/index.astro index 936e98979e5a..abd3d4299055 100644 --- a/packages/astro/test/fixtures/react-component/src/pages/index.astro +++ b/packages/astro/test/fixtures/react-component/src/pages/index.astro @@ -7,6 +7,7 @@ import {Research2} from '../components/Research.jsx'; import Pure from '../components/Pure.jsx'; import TypeScriptComponent from '../components/TypeScriptComponent'; import CloneElement from '../components/CloneElement'; +import WithChildren from '../components/WithChildren'; const someProps = { text: 'Hello world!', @@ -31,5 +32,7 @@ const someProps = { + test + diff --git a/packages/astro/test/react-component.test.js b/packages/astro/test/react-component.test.js index 19bd42a431fb..8c22cc861b23 100644 --- a/packages/astro/test/react-component.test.js +++ b/packages/astro/test/react-component.test.js @@ -42,11 +42,16 @@ describe('React Components', () => { expect($('#pure')).to.have.lengthOf(1); // test 8: Check number of islands - expect($('astro-island[uid]')).to.have.lengthOf(5); + expect($('astro-island[uid]')).to.have.lengthOf(7); // test 9: Check island deduplication const uniqueRootUIDs = new Set($('astro-island').map((i, el) => $(el).attr('uid'))); - expect(uniqueRootUIDs.size).to.equal(4); + expect(uniqueRootUIDs.size).to.equal(6); + + // test 10: Should properly render children passed as props + const islandsWithChildren = $('.with-children'); + expect(islandsWithChildren).to.have.lengthOf(2); + expect($(islandsWithChildren[0]).html()).to.equal($(islandsWithChildren[1]).html()); }); it('Can load Vue', async () => { diff --git a/packages/integrations/react/server-v17.js b/packages/integrations/react/server-v17.js index 8613ef01a098..ab5b06350bb6 100644 --- a/packages/integrations/react/server-v17.js +++ b/packages/integrations/react/server-v17.js @@ -62,8 +62,11 @@ function renderToStaticMarkup(Component, props, { default: children, ...slotted const newProps = { ...props, ...slots, - children: children != null ? React.createElement(StaticHtml, { value: children }) : undefined, }; + const newChildren = children ?? props.children; + if (newChildren != null) { + newProps.children = React.createElement(StaticHtml, { value: newChildren }); + } const vnode = React.createElement(Component, newProps); let html; if (metadata && metadata.hydrate) { diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js index 1ebd044cffff..01a135a9ba4c 100644 --- a/packages/integrations/react/server.js +++ b/packages/integrations/react/server.js @@ -69,8 +69,9 @@ async function renderToStaticMarkup(Component, props, { default: children, ...sl ...props, ...slots, }; - if (children != null) { - newProps.children = React.createElement(StaticHtml, { value: children }); + const newChildren = children ?? props.children; + if (newChildren != null) { + newProps.children = React.createElement(StaticHtml, { value: newChildren }); } const vnode = React.createElement(Component, newProps); let html;