diff --git a/reflex/.templates/jinja/web/utils/context.js.jinja2 b/reflex/.templates/jinja/web/utils/context.js.jinja2 index caee4e0ca..5f734a0c3 100644 --- a/reflex/.templates/jinja/web/utils/context.js.jinja2 +++ b/reflex/.templates/jinja/web/utils/context.js.jinja2 @@ -26,6 +26,8 @@ export const clientStorage = {} {% if state_name %} export const state_name = "{{state_name}}" +export const exception_state_name = "{{const.frontend_exception_state}}" + // Theses events are triggered on initial load and each page navigation. export const onLoadInternalEvent = () => { const internal_events = []; diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index b20b80391..f7fbf17f1 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/web/utils/state.js @@ -11,6 +11,7 @@ import { initialState, onLoadInternalEvent, state_name, + exception_state_name, } from "utils/context.js"; import debounce from "/utils/helpers/debounce"; import throttle from "/utils/helpers/throttle"; @@ -698,7 +699,7 @@ export const useEventLoop = ( } window.onerror = function (msg, url, lineNo, columnNo, error) { - addEvents([Event("state.frontend_event_exception_state.handle_frontend_exception", { + addEvents([Event(`${exception_state_name}.handle_frontend_exception`, { stack: error.stack, })]) return false; @@ -707,7 +708,7 @@ export const useEventLoop = ( //NOTE: Only works in Chrome v49+ //https://github.com/mknichel/javascript-errors?tab=readme-ov-file#promise-rejection-events window.onunhandledrejection = function (event) { - addEvents([Event("state.frontend_event_exception_state.handle_frontend_exception", { + addEvents([Event(`${exception_state_name}.handle_frontend_exception`, { stack: event.reason.stack, })]) return false; diff --git a/reflex/app.py b/reflex/app.py index 9c40db195..658ba1a1f 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -132,14 +132,17 @@ def default_overlay_component() -> Component: ) -def default_error_boundary() -> Component: +def default_error_boundary(*children: Component) -> Component: """Default error_boundary attribute for App. + Args: + *children: The children to render in the error boundary. + Returns: The default error_boundary, which is an ErrorBoundary. """ - return ErrorBoundary.create() + return ErrorBoundary.create(*children) class OverlayFragment(Fragment): @@ -184,9 +187,7 @@ class App(MiddlewareMixin, LifespanMixin, Base): ) # Error boundary component to wrap the app with. - error_boundary: Optional[Union[Component, ComponentCallable]] = ( - default_error_boundary - ) + error_boundary: Optional[ComponentCallable] = default_error_boundary # Components to add to the head of every page. head_components: List[Component] = [] @@ -751,7 +752,7 @@ class App(MiddlewareMixin, LifespanMixin, Base): if self.error_boundary is None: return component - component = ErrorBoundary.create(*component.children) + component = self.error_boundary(*component.children) return component diff --git a/reflex/compiler/templates.py b/reflex/compiler/templates.py index c45e7bb90..7e900a68d 100644 --- a/reflex/compiler/templates.py +++ b/reflex/compiler/templates.py @@ -44,6 +44,7 @@ class ReflexJinjaEnvironment(Environment): "hydrate": constants.CompileVars.HYDRATE, "on_load_internal": constants.CompileVars.ON_LOAD_INTERNAL, "update_vars_internal": constants.CompileVars.UPDATE_VARS_INTERNAL, + "frontend_exception_state": constants.CompileVars.FRONTEND_EXCEPTION_STATE, } diff --git a/reflex/constants/compiler.py b/reflex/constants/compiler.py index 3b1f480d2..83bef4429 100644 --- a/reflex/constants/compiler.py +++ b/reflex/constants/compiler.py @@ -65,6 +65,8 @@ class CompileVars(SimpleNamespace): ON_LOAD_INTERNAL = "on_load_internal_state.on_load_internal" # The name of the internal event to update generic state vars. UPDATE_VARS_INTERNAL = "update_vars_internal_state.update_vars_internal" + # The name of the frontend event exception state + FRONTEND_EXCEPTION_STATE = "state.frontend_event_exception_state" class PageNames(SimpleNamespace): @@ -124,14 +126,14 @@ class Hooks(SimpleNamespace): } })""" - FRONTEND_ERRORS = """ - const logFrontendError = (error, info) => { - if (process.env.NODE_ENV === "production") { - addEvents([Event("frontend_event_exception_state.handle_frontend_exception", { + FRONTEND_ERRORS = f""" + const logFrontendError = (error, info) => {{ + if (process.env.NODE_ENV === "production") {{ + addEvents([Event("{CompileVars.FRONTEND_EXCEPTION_STATE}.handle_frontend_exception", {{ stack: error.stack, - })]) - } - } + }})]) + }} + }} """