diff --git a/reflex/state.py b/reflex/state.py index 5116069ab6..1b5eda865a 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -93,6 +93,9 @@ def __init__(self, *args, parent_state: State | None = None, **kwargs): *args: The args to pass to the Pydantic init method. parent_state: The parent state. **kwargs: The kwargs to pass to the Pydantic init method. + + Raises: + ValueError: If a substate class shadows another. """ kwargs["parent_state"] = parent_state super().__init__(*args, **kwargs) @@ -103,7 +106,13 @@ def __init__(self, *args, parent_state: State | None = None, **kwargs): # Setup the substates. for substate in self.get_substates(): - self.substates[substate.get_name()] = substate(parent_state=self) + substate_name = substate.get_name() + if substate_name in self.substates: + raise ValueError( + f"The substate class '{substate_name}' has been defined multiple times. Shadowing " + f"substate classes is not allowed." + ) + self.substates[substate_name] = substate(parent_state=self) # Convert the event handlers to functions. self._init_event_handlers() diff --git a/tests/conftest.py b/tests/conftest.py index 026ae47bcb..895954afad 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -584,3 +584,23 @@ def reassign_mutables(self): self.test_set = {1, 2, 3, 4, "five"} return MutableTestState() + + +@pytest.fixture +def duplicate_substate(): + """Create a Test state that has duplicate child substates. + + Returns: + The test state. + """ + + class TestState(rx.State): + pass + + class ChildTestState(TestState): # type: ignore # noqa + pass + + class ChildTestState(TestState): # type: ignore # noqa + pass + + return TestState diff --git a/tests/test_state.py b/tests/test_state.py index 8240c961ca..763d36a6dd 100644 --- a/tests/test_state.py +++ b/tests/test_state.py @@ -1583,3 +1583,8 @@ def assert_custom_dirty(): assert_custom_dirty() mutable_state._be_custom.custom.bar = "baz" assert_custom_dirty() + + +def test_duplicate_substate_class(duplicate_substate): + with pytest.raises(ValueError): + duplicate_substate()