Skip to content

Commit 6655a80

Browse files
Fix PyScript root component not hiding after render error (#1347)
1 parent b3eabbb commit 6655a80

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

src/reactpy/executors/pyscript/layout_handler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ def update_model(update, root_model):
2828
if update["path"]:
2929
set_pointer(root_model, update["path"], update["model"])
3030
else:
31+
# clear old keys first, dict.update() alone would keep stale "children" around when the new model doesn't have any
32+
root_model.clear()
3133
root_model.update(update["model"])
3234

3335
def render_html(self, layout, model):
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from reactpy import component, hooks, html
2+
3+
4+
@component
5+
def root():
6+
count, set_count = hooks.use_state(0)
7+
8+
def increment(event):
9+
set_count(count + 1)
10+
11+
# crash on purpose after a few clicks, same as the real bug report
12+
if count == 3:
13+
raise ValueError("This error should hide the root component")
14+
15+
return html.div(
16+
html.button(
17+
{"onClick": increment, "id": "incr", "data-count": count}, "Increment"
18+
),
19+
html.p(f"PyScript Count: {count}"),
20+
)

tests/test_pyscript/test_components.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,33 @@ def CustomRootName():
6868
await display.page.wait_for_selector("#incr[data-count='3']")
6969

7070

71+
async def test_root_component_error_hides_component(display: DisplayFixture):
72+
"""A crash in the root render should hide it, not leave stale content stuck
73+
on the page."""
74+
75+
@reactpy.component
76+
def Counter():
77+
return pyscript_component(
78+
Path(__file__).parent / "pyscript_components" / "root_error.py",
79+
initial=html.div({"id": "loading"}, "Loading..."),
80+
)
81+
82+
await display.show(Counter)
83+
84+
await display.page.wait_for_selector("#loading")
85+
await display.page.wait_for_selector("#incr")
86+
87+
await display.page.click("#incr")
88+
await display.page.wait_for_selector("#incr[data-count='1']")
89+
90+
await display.page.click("#incr")
91+
await display.page.wait_for_selector("#incr[data-count='2']")
92+
93+
# this click flips count to 3 -> root component raises -> button should vanish
94+
await display.page.click("#incr")
95+
await display.page.wait_for_selector("#incr", state="detached")
96+
97+
7198
def test_bad_file_path():
7299
with pytest.raises(ValueError):
73100
pyscript_component(initial=html.div({"id": "loading"}, "Loading...")).render()

0 commit comments

Comments
 (0)