Skip to content

Commit

Permalink
[labs/ssr-react] Handle children passed in via props (#3861)
Browse files Browse the repository at this point in the history
  • Loading branch information
augustjk committed May 3, 2023
1 parent dc5f964 commit 8deca6e
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-peas-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lit-labs/ssr-react': patch
---

Handle children passed in via props
19 changes: 15 additions & 4 deletions packages/labs/ssr-react/src/lib/node/wrap-create-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {renderCustomElement} from './render-custom-element.js';
import type {
createElement as ReactCreateElement,
ElementType,
PropsWithChildren,
ReactElement,
ReactNode,
} from 'react';
Expand All @@ -23,9 +24,9 @@ export function wrapCreateElement(
// non-React alternatives like preact?
originalCreateElement: typeof ReactCreateElement
) {
return function createElement<P extends {}>(
return function createElement<P>(
type: ElementType<P>,
props: P,
props: PropsWithChildren<P> | null,
...children: ReactNode[]
): ReactElement {
if (isCustomElement(type)) {
Expand All @@ -40,11 +41,21 @@ export function wrapCreateElement(
},
});

const newChildren: ReactNode[] = [templateShadowRoot];
// React.createElement prefers children arguments over props.children
// https://github.com/facebook/react/blob/v18.2.0/packages/react/src/ReactElement.js#L401-L417
if (children.length > 0) {
newChildren.push(...children);
} else if (Array.isArray(props?.children)) {
newChildren.push(...props!.children);
} else if (props?.children !== undefined) {
newChildren.push(props.children);
}

return originalCreateElement(
type,
{...props, ...elementAttributes},
templateShadowRoot,
...children
...newChildren
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,73 @@ test('single element with dynamic children', () => {
);
});

test('single element with string child via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element children="some string child"></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template>some string child</test-element>`
);
});

test('single element with element child via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element children={<span>span child</span>}></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template><span>span child</span></test-element>`
);
});

test('single element with multiple children via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element
children={
<>
<span>span</span>
<p>p</p>
</>
}
></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template><span>span</span><p>p</p></test-element>`
);
});

test('single element with dynamic children via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element
children={[1, 2, 3].map((i) => (
<span key={i}>{i}</span>
))}
></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template><span>1</span><span>2</span><span>3</span></test-element>`
);
});

test('nested element', () => {
assert.equal(
ReactDOMServer.renderToString(
Expand Down
67 changes: 67 additions & 0 deletions packages/labs/ssr-react/src/test/integration/runtime-jsx_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,73 @@ test('single element with dynamic children', () => {
);
});

test('single element with string child via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element children="some string child"></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template>some string child</test-element>`
);
});

test('single element with element child via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element children={<span>span child</span>}></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template><span>span child</span></test-element>`
);
});

test('single element with multiple children via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element
children={
<>
<span>span</span>
<p>p</p>
</>
}
></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template><span>span</span><p>p</p></test-element>`
);
});

test('single element with dynamic children via props', () => {
assert.equal(
ReactDOMServer.renderToString(
<test-element
children={[1, 2, 3].map((i) => (
<span key={i}>{i}</span>
))}
></test-element>
),
`<test-element><template shadowroot="open" shadowrootmode="open"><style>
p {
color: blue;
}
</style><!--lit-part aHUgh01By8I=--><p>Hello, <!--lit-part-->Somebody<!--/lit-part-->!</p>
<slot></slot><!--/lit-part--></template><span>1</span><span>2</span><span>3</span></test-element>`
);
});

test('nested element', () => {
assert.equal(
ReactDOMServer.renderToString(
Expand Down

0 comments on commit 8deca6e

Please sign in to comment.