Skip to content

Commit 64d2f37

Browse files
Fix SSR @component functions rendering under CSR components (#1324)
Co-authored-by: Archmonger <16909269+Archmonger@users.noreply.github.com>
1 parent d07e25e commit 64d2f37

File tree

5 files changed

+49
-3
lines changed

5 files changed

+49
-3
lines changed

src/js/packages/@reactpy/client/src/vdom.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import eventToObject from "event-to-object";
2+
import { Fragment } from "preact";
23
import type {
34
ReactPyVdom,
45
ReactPyVdomImportSource,
@@ -93,7 +94,7 @@ function createImportSourceElement(props: {
9394
}
9495
}
9596
} else {
96-
type = props.model.tagName;
97+
type = props.model.tagName === "" ? Fragment : props.model.tagName;
9798
}
9899
return props.binding.create(
99100
type,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from "https://esm.sh/react@19.0"
2+
import ReactDOM from "https://esm.sh/react-dom@19.0/client"
3+
import {Container} from "https://esm.sh/react-bootstrap@2.10.10/?deps=react@19.0,react-dom@19.0,react-is@19.0&exports=Container";
4+
export {Container};
5+
6+
export function bind(node, config) {
7+
const root = ReactDOM.createRoot(node);
8+
return {
9+
create: (type, props, children) =>
10+
React.createElement(type, props, children),
11+
render: (element) => root.render(element, node),
12+
unmount: () => root.unmount()
13+
};
14+
}

tests/test_reactjs/test_modules.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
from pathlib import Path
2+
13
import pytest
24

35
import reactpy
46
from reactpy import html
57
from reactpy.reactjs import component_from_string, import_reactjs
68
from reactpy.testing import BackendFixture, DisplayFixture
79

10+
JS_FIXTURES_DIR = Path(__file__).parent / "js_fixtures"
11+
812

913
@pytest.fixture(scope="module")
1014
async def display(browser):
@@ -89,3 +93,24 @@ def App():
8993
elements = await display.page.query_selector_all(".component-c")
9094
assert len(elements) == 2
9195
await display.page.wait_for_selector("#deep-server")
96+
97+
98+
async def test_nest_custom_component_under_web_component(display: DisplayFixture):
99+
"""
100+
Fix https://github.com/reactive-python/reactpy/discussions/1323
101+
102+
Custom components (i.e those wrapped in the component decorator) were not able to
103+
be nested under web components.
104+
"""
105+
Container = reactpy.reactjs.component_from_file(
106+
JS_FIXTURES_DIR / "nest-custom-under-web.js", "Container", name="nest-custom-under-web"
107+
)
108+
109+
@reactpy.component
110+
def CustomComponent():
111+
return reactpy.html.div(reactpy.html.h1({"id": "my-header"}, "Header 1"))
112+
113+
await display.show(lambda: Container(CustomComponent()))
114+
115+
element = await display.page.wait_for_selector("#my-header", state="attached")
116+
assert await element.inner_text() == "Header 1"

tests/test_web/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"""
2+
THESE ARE TESTS FOR THE LEGACY API. SEE tests/test_reactjs/* FOR THE NEW API TESTS.
3+
THE CONTENTS OF THIS MODULE WILL BE MIGRATED OR DELETED ONCE THE LEGACY API IS REMOVED.
4+
"""

tests/test_web/test_module.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
# THESE ARE TESTS FOR THE LEGACY API. SEE tests/test_reactjs/* FOR THE NEW API TESTS.
2-
# THIS MODULE WILL BE MIGRATED OR DELETED ONCE THE LEGACY API IS REMOVED.
1+
"""
2+
THESE ARE TESTS FOR THE LEGACY API. SEE tests/test_reactjs/* FOR THE NEW API TESTS.
3+
THE CONTENTS OF THIS MODULE WILL BE MIGRATED OR DELETED ONCE THE LEGACY API IS REMOVED.
4+
"""
35
from pathlib import Path
46

57
import pytest

0 commit comments

Comments
 (0)