Skip to content

Commit 16518bf

Browse files
authored
feat: check for key mutation when removing children (#35)
1 parent 1f228b4 commit 16518bf

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

reacton/core.py

+4
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def __init__(self, component, args=None, kwargs=None):
230230
self._meta = {}
231231
# for debugging/testing only
232232
self._render_count = 0
233+
self._key_frozen: bool = False
233234

234235
rc = _get_render_context(required=False)
235236
if rc is not None and rc.container_adders:
@@ -269,6 +270,8 @@ def key(self, value: str):
269270
270271
This can help render performance. See documentation for details.
271272
"""
273+
if self._key_frozen:
274+
raise RuntimeError("Element keys should not be mutated after rendering")
272275
self._key = value
273276
return self
274277

@@ -1588,6 +1591,7 @@ def _render(self, element: Element, default_key: str, parent_key: str):
15881591
key = el._key
15891592
if key is None:
15901593
key = default_key
1594+
el._key_frozen = True
15911595

15921596
logger.debug("Render: (%s,%s) - %r", parent_key, key, element)
15931597

reacton/core_test.py

+22
Original file line numberDiff line numberDiff line change
@@ -3186,3 +3186,25 @@ def Test():
31863186
assert vbox.children[0].description == "1"
31873187
assert vbox.children[1].description == "2"
31883188
rc.close()
3189+
3190+
3191+
def test_key_mutate_protection(Container):
3192+
button = ButtonComponentFunction(description="Hi")
3193+
set_state = lambda value: None # noqa
3194+
3195+
@react.component
3196+
def Test():
3197+
nonlocal set_state
3198+
state, set_state = react.use_state(0)
3199+
if state == 0:
3200+
return Container(children=[button])
3201+
else:
3202+
return Container(children=[button.key("i_should_not_be_mutated")]).key("bla")
3203+
3204+
box, rc = react.render(Test(), handle_error=False)
3205+
assert rc.find(widgets.Button).widget.description == "Hi"
3206+
assert button._key is None
3207+
with pytest.raises(RuntimeError, match="Element keys should not be mutated after rendering"):
3208+
set_state(1)
3209+
rc.render(w.HTML(value="recover").key("HTML"))
3210+
rc.close()

0 commit comments

Comments
 (0)