[REF-2158] Enable state when on_load
or event_triggers are set. (#2815)
* [REF-2158] Enable state when `on_load` or event_triggers are set. Basically all events in a reflex app require the backend to be up, even the built-in server side events round trip to the backend and require "state" even if no user-defined state classes are declared. test_app_state_determination: checking that state is enabled at the right time * Clear out DECORATED_PAGES when initializing a new app
This commit is contained in:
parent
bf297e2f5b
commit
e085dcab49
@ -453,14 +453,18 @@ class App(Base):
|
||||
# Generate the component if it is a callable.
|
||||
component = self._generate_component(component)
|
||||
|
||||
# Ensure state is enabled if this page uses state.
|
||||
if self.state is None:
|
||||
for var in component._get_vars(include_children=True):
|
||||
if not var._var_data:
|
||||
continue
|
||||
if not var._var_data.state:
|
||||
continue
|
||||
if on_load or component._has_event_triggers():
|
||||
self.enable_state()
|
||||
break
|
||||
else:
|
||||
for var in component._get_vars(include_children=True):
|
||||
if not var._var_data:
|
||||
continue
|
||||
if not var._var_data.state:
|
||||
continue
|
||||
self.enable_state()
|
||||
break
|
||||
|
||||
component = OverlayFragment.create(component)
|
||||
|
||||
|
@ -873,6 +873,20 @@ class Component(BaseComponent, ABC):
|
||||
|
||||
return vars
|
||||
|
||||
def _has_event_triggers(self) -> bool:
|
||||
"""Check if the component or children have any event triggers.
|
||||
|
||||
Returns:
|
||||
True if the component or children have any event triggers.
|
||||
"""
|
||||
if self.event_triggers:
|
||||
return True
|
||||
else:
|
||||
for child in self.children:
|
||||
if isinstance(child, Component) and child._has_event_triggers():
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_custom_code(self) -> str | None:
|
||||
"""Get custom code for the component.
|
||||
|
||||
|
@ -225,6 +225,8 @@ class AppHarness:
|
||||
with chdir(self.app_path):
|
||||
# ensure config and app are reloaded when testing different app
|
||||
reflex.config.get_config(reload=True)
|
||||
# Clean out any `rx.page` decorators from other tests.
|
||||
reflex.app.DECORATED_PAGES.clear()
|
||||
# reset rx.State subclasses
|
||||
State.class_subclasses.clear()
|
||||
State.class_subclasses.update(INTERNAL_STATES)
|
||||
|
@ -1319,3 +1319,38 @@ def test_app_wrap_priority(compilable_app):
|
||||
")"
|
||||
"}"
|
||||
) in "".join(app_js_lines)
|
||||
|
||||
|
||||
def test_app_state_determination():
|
||||
"""Test that the stateless status of an app is determined correctly."""
|
||||
a1 = App()
|
||||
assert a1.state is None
|
||||
|
||||
# No state, no router, no event handlers.
|
||||
a1.add_page(rx.box("Index"), route="/")
|
||||
assert a1.state is None
|
||||
|
||||
# Add a page with `on_load` enables state.
|
||||
a1.add_page(rx.box("About"), route="/about", on_load=rx.console_log(""))
|
||||
assert a1.state is not None
|
||||
|
||||
a2 = App()
|
||||
assert a2.state is None
|
||||
|
||||
# Referencing a state Var enables state.
|
||||
a2.add_page(rx.box(rx.text(GenState.value)), route="/")
|
||||
assert a2.state is not None
|
||||
|
||||
a3 = App()
|
||||
assert a3.state is None
|
||||
|
||||
# Referencing router enables state.
|
||||
a3.add_page(rx.box(rx.text(State.router.page.full_path)), route="/")
|
||||
assert a3.state is not None
|
||||
|
||||
a4 = App()
|
||||
assert a4.state is None
|
||||
|
||||
# Referencing an event handler enables state.
|
||||
a4.add_page(rx.box(rx.button("Click", on_click=rx.console_log(""))), route="/")
|
||||
assert a4.state is not None
|
||||
|
Loading…
Reference in New Issue
Block a user