Explorar el Código

do not add auto setters on reflex states (#5314)

* do not add auto setters on reflex states

* fix call script and input

* enable auto setters

* fix the tests by not changing the payload to set_is_hydrated

* darglint, dang it

* handle the dynamic case
Khaleel Al-Adhami hace 5 días
padre
commit
69ca396063

+ 24 - 3
reflex/state.py

@@ -1003,6 +1003,18 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
             raise ValueError(f"Invalid path: {path}")
             raise ValueError(f"Invalid path: {path}")
         return getattr(substate, name)
         return getattr(substate, name)
 
 
+    @classmethod
+    def is_user_defined(cls) -> bool:
+        """Check if the state is user-defined.
+
+        Returns:
+            True if the state is user-defined, False otherwise.
+        """
+        return (
+            not cls.__module__.startswith("reflex.")
+            or cls.__module__ == "reflex.istate.dynamic"
+        )
+
     @classmethod
     @classmethod
     def _init_var(cls, prop: Var):
     def _init_var(cls, prop: Var):
         """Initialize a variable.
         """Initialize a variable.
@@ -1024,7 +1036,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
                 f'Found var "{prop._js_expr}" with type {prop._var_type}.'
                 f'Found var "{prop._js_expr}" with type {prop._var_type}.'
             )
             )
         cls._set_var(prop)
         cls._set_var(prop)
-        if get_config().state_auto_setters:
+        if cls.is_user_defined() and get_config().state_auto_setters:
             cls._create_setter(prop)
             cls._create_setter(prop)
         cls._set_default_value(prop)
         cls._set_default_value(prop)
 
 
@@ -2330,6 +2342,15 @@ class State(BaseState):
     # The hydrated bool.
     # The hydrated bool.
     is_hydrated: bool = False
     is_hydrated: bool = False
 
 
+    @event
+    def set_is_hydrated(self, value: bool) -> None:
+        """Set the hydrated state.
+
+        Args:
+            value: The hydrated state.
+        """
+        self.is_hydrated = value
+
 
 
 T = TypeVar("T", bound=BaseState)
 T = TypeVar("T", bound=BaseState)
 
 
@@ -2424,7 +2445,7 @@ class OnLoadInternalState(State):
     This is a separate substate to avoid deserializing the entire state tree for every page navigation.
     This is a separate substate to avoid deserializing the entire state tree for every page navigation.
     """
     """
 
 
-    def on_load_internal(self) -> list[Event | EventSpec] | None:
+    def on_load_internal(self) -> list[Event | EventSpec | event.EventCallback] | None:
         """Queue on_load handlers for the current page.
         """Queue on_load handlers for the current page.
 
 
         Returns:
         Returns:
@@ -2444,7 +2465,7 @@ class OnLoadInternalState(State):
                 self.router.session.client_token,
                 self.router.session.client_token,
                 router_data=self.router_data,
                 router_data=self.router_data,
             ),
             ),
-            State.set_is_hydrated(True),  # pyright: ignore [reportAttributeAccessIssue]
+            State.set_is_hydrated(True),
         ]
         ]
 
 
 
 

+ 16 - 0
tests/integration/test_call_script.py

@@ -182,6 +182,22 @@ def CallScript():
                 callback=CallScriptState.setvar("last_result"),
                 callback=CallScriptState.setvar("last_result"),
             )
             )
 
 
+        @rx.event
+        def set_inline_counter(self, value: str):
+            self.inline_counter = int(value)
+
+        @rx.event
+        def set_external_counter(self, value: str):
+            self.external_counter = int(value)
+
+        @rx.event
+        def set_last_result(self, value: str):
+            self.last_result = int(value)
+
+        @rx.event
+        def set_value(self, value: str):
+            self.value = value
+
         @rx.event
         @rx.event
         def reset_(self):
         def reset_(self):
             yield rx.call_script("inline_counter = 0; external_counter = 0")
             yield rx.call_script("inline_counter = 0; external_counter = 0")

+ 8 - 0
tests/integration/test_client_storage.py

@@ -30,6 +30,14 @@ def ClientSide():
         state_var: str = ""
         state_var: str = ""
         input_value: str = ""
         input_value: str = ""
 
 
+        @rx.event
+        def set_state_var(self, value: str):
+            self.state_var = value
+
+        @rx.event
+        def set_input_value(self, value: str):
+            self.input_value = value
+
     class ClientSideSubState(ClientSideState):
     class ClientSideSubState(ClientSideState):
         # cookies with default settings
         # cookies with default settings
         c1: str = rx.Cookie()
         c1: str = rx.Cookie()

+ 6 - 2
tests/integration/test_input.py

@@ -16,6 +16,10 @@ def FullyControlledInput():
     class State(rx.State):
     class State(rx.State):
         text: str = "initial"
         text: str = "initial"
 
 
+        @rx.event
+        def set_text(self, text: str):
+            self.text = text
+
     app = rx.App()
     app = rx.App()
 
 
     @app.add_page
     @app.add_page
@@ -26,11 +30,11 @@ def FullyControlledInput():
             ),
             ),
             rx.input(
             rx.input(
                 id="debounce_input_input",
                 id="debounce_input_input",
-                on_change=State.set_text,  # pyright: ignore [reportAttributeAccessIssue]
+                on_change=State.set_text,
                 value=State.text,
                 value=State.text,
             ),
             ),
             rx.input(value=State.text, id="value_input", is_read_only=True),
             rx.input(value=State.text, id="value_input", is_read_only=True),
-            rx.input(on_change=State.set_text, id="on_change_input"),  # pyright: ignore [reportAttributeAccessIssue]
+            rx.input(on_change=State.set_text, id="on_change_input"),
             rx.el.input(
             rx.el.input(
                 value=State.text,
                 value=State.text,
                 id="plain_value_input",
                 id="plain_value_input",