@@ -398,6 +398,9 @@ class App(MiddlewareMixin, LifespanMixin):
398398 # The state class to use for the app.
399399 _state : type [BaseState ] | None = None
400400
401+ # Whether to enable state for the app. If False, the app will not use state.
402+ enable_state : bool = True
403+
401404 # Class to manage many client states.
402405 _state_manager : StateManager | None = None
403406
@@ -475,7 +478,8 @@ def __post_init__(self):
475478 if issubclass (clz , AppMixin ):
476479 clz ._init_mixin (self )
477480
478- self ._setup_state ()
481+ if self .enable_state :
482+ self ._enable_state ()
479483
480484 # Set up the admin dash.
481485 self ._setup_admin_dash ()
@@ -490,7 +494,7 @@ def _enable_state(self) -> None:
490494 """Enable state for the app."""
491495 if not self ._state :
492496 self ._state = State
493- self ._setup_state ()
497+ self ._setup_state ()
494498
495499 def _setup_state (self ) -> None :
496500 """Set up the state for the app.
@@ -589,21 +593,16 @@ def __call__(self) -> ASGIApp:
589593 Returns:
590594 The backend api.
591595 """
596+ from reflex .vars .base import GLOBAL_CACHE
597+
592598 # For py3.9 compatibility when redis is used, we MUST add any decorator pages
593599 # before compiling the app in a thread to avoid event loop error (REF-2172).
594600 self ._apply_decorated_pages ()
595601
596- compile_future = concurrent .futures .ThreadPoolExecutor (max_workers = 1 ).submit (
597- self ._compile , prerender_routes = is_prod_mode ()
598- )
599-
600- def callback (f : concurrent .futures .Future ):
601- # Force background compile errors to print eagerly
602- return f .result ()
602+ self ._compile (prerender_routes = is_prod_mode ())
603603
604- compile_future .add_done_callback (callback )
605- # Wait for the compile to finish to ensure all optional endpoints are mounted.
606- compile_future .result ()
604+ # We will not be making more vars, so we can clear the global cache to free up memory.
605+ GLOBAL_CACHE .clear ()
607606
608607 if not self ._api :
609608 msg = "The app has not been initialized."
@@ -837,14 +836,10 @@ def _compile_page(self, route: str, save_page: bool = True):
837836 save_page: If True, the compiled page is saved to self._pages.
838837 """
839838 n_states_before = len (all_base_state_classes )
840- component , enable_state = compiler .compile_unevaluated_page (
841- route , self ._unevaluated_pages [route ], self ._state , self . style , self .theme
839+ component = compiler .compile_unevaluated_page (
840+ route , self ._unevaluated_pages [route ], self .style , self .theme
842841 )
843842
844- # Indicate that the app should use state.
845- if enable_state :
846- self ._enable_state ()
847-
848843 # Indicate that evaluating this page creates one or more state classes.
849844 if len (all_base_state_classes ) > n_states_before :
850845 self ._stateful_pages [route ] = None
@@ -1138,7 +1133,6 @@ def get_compilation_time() -> str:
11381133 for route in stateful_pages :
11391134 console .debug (f"BE Evaluating stateful page: { route } " )
11401135 self ._compile_page (route , save_page = False )
1141- self ._enable_state ()
11421136 self ._add_optional_endpoints ()
11431137 return
11441138
@@ -1337,8 +1331,6 @@ def memoized_toast_provider():
13371331 for route , component in zip (self ._pages , page_components , strict = True ):
13381332 ExecutorSafeFunctions .COMPONENTS [route ] = component
13391333
1340- ExecutorSafeFunctions .STATE = self ._state
1341-
13421334 modify_files_tasks : list [tuple [str , str , Callable [[str ], str ]]] = []
13431335
13441336 with console .timing ("Compile to Javascript" ), executor as executor :
0 commit comments