diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/jinja/web/utils/state.js.jinja2 similarity index 99% rename from reflex/.templates/web/utils/state.js rename to reflex/.templates/jinja/web/utils/state.js.jinja2 index 5d14abaed0..348f020d09 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/jinja/web/utils/state.js.jinja2 @@ -768,7 +768,7 @@ export const useEventLoop = ( const vars = {}; vars[storage_to_state_map[e.key]] = e.newValue; const event = Event( - `${state_name}.{{ update_vars_internal }}`, + `${state_name}.{{ const.update_vars_internal }}`, { vars: vars } ); addEvents([event], e); @@ -782,7 +782,7 @@ export const useEventLoop = ( // Route after the initial page hydration. useEffect(() => { const change_start = () => { - const main_state_dispatch = dispatch["state"] + const main_state_dispatch = dispatch["{{ const.state_name }}"] if (main_state_dispatch !== undefined) { main_state_dispatch({ is_hydrated: false }) } diff --git a/reflex/app.py b/reflex/app.py index 7e40a95bf7..a476d738c8 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -943,6 +943,8 @@ def get_compilation_time() -> str: compile_results.append( compiler.compile_contexts(self.state, self.theme), ) + # Compile the state + compile_results.append(compiler.compile_state()) # Fix #2992 by removing the top-level appearance prop if self.theme is not None: self.theme.appearance = None diff --git a/reflex/compiler/compiler.py b/reflex/compiler/compiler.py index 2567624e8a..08c823659f 100644 --- a/reflex/compiler/compiler.py +++ b/reflex/compiler/compiler.py @@ -102,6 +102,15 @@ def _compile_contexts(state: Optional[Type[BaseState]], theme: Component | None) ) +def _compile_state() -> str: + """Compile the state. + + Returns: + The compiled state. + """ + return templates.state().render() + + def _compile_page( component: Component, state: Type[BaseState], @@ -400,6 +409,18 @@ def compile_contexts( return output_path, _compile_contexts(state, theme) +def compile_state() -> tuple[str, str]: + """Compile the state. + + Returns: + The path and code of the compiled state. + """ + output_path = utils.get_state_path() + + code = _compile_state() + return output_path, code + + def compile_page( path: str, component: Component, state: Type[BaseState] ) -> tuple[str, str]: diff --git a/reflex/compiler/templates.py b/reflex/compiler/templates.py index debb20a3d2..aa7628bb87 100644 --- a/reflex/compiler/templates.py +++ b/reflex/compiler/templates.py @@ -14,6 +14,7 @@ def __init__(self) -> None: from reflex.state import ( FrontendEventExceptionState, OnLoadInternalState, + State, UpdateVarsInternalState, ) @@ -48,6 +49,7 @@ def __init__(self) -> None: "set_color_mode": constants.ColorMode.SET, "use_color_mode": constants.ColorMode.USE, "hydrate": constants.CompileVars.HYDRATE, + "state_name": State.get_name(), "on_load_internal": f"{OnLoadInternalState.get_name()}.on_load_internal", "update_vars_internal": f"{UpdateVarsInternalState.get_name()}.update_vars_internal", "frontend_exception_state": FrontendEventExceptionState.get_full_name(), @@ -111,6 +113,15 @@ def context(): return get_template("web/utils/context.js.jinja2") +def state(): + """Template for the state file. + + Returns: + Template: The template for the state file. + """ + return get_template("web/utils/state.js.jinja2") + + def tailwind_config(): """Template for Tailwind config. diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index 1b69539ac7..631418b2bf 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -382,6 +382,15 @@ def get_context_path() -> str: return str(get_web_dir() / (constants.Dirs.CONTEXTS_PATH + constants.Ext.JS)) +def get_state_path() -> str: + """Get the path of the state file. + + Returns: + The path of the state module. + """ + return str(get_web_dir() / (constants.Dirs.STATES_PATH + constants.Ext.JS)) + + def get_components_path() -> str: """Get the path of the compiled components. diff --git a/reflex/constants/base.py b/reflex/constants/base.py index 65d957d276..ae463c3ba4 100644 --- a/reflex/constants/base.py +++ b/reflex/constants/base.py @@ -31,6 +31,8 @@ class Dirs(SimpleNamespace): COMPONENTS_PATH = "/".join([UTILS, "components"]) # The name of the contexts file. CONTEXTS_PATH = "/".join([UTILS, "context"]) + # The name of the states file. + STATES_PATH = "/".join([UTILS, "state"]) # The name of the output static directory. STATIC = "_static" # The name of the public html directory served at "/"