1111import functools
1212import inspect
1313import pickle
14+ import re
1415import sys
1516import time
1617import typing
1718import warnings
18- from collections .abc import AsyncIterator , Callable , Sequence
19+ from collections .abc import AsyncIterator , Callable , Iterator , Sequence
1920from enum import Enum
2021from hashlib import md5
2122from importlib .util import find_spec
3435 Event ,
3536 EventHandler ,
3637 EventSpec ,
38+ call_script ,
3739 fix_events ,
3840)
3941from reflex .istate import HANDLED_PICKLE_ERRORS , debug_failed_pickles
@@ -2470,11 +2472,26 @@ def wrapper() -> Component:
24702472 return wrapper
24712473
24722474
2475+ # sessionStorage key holding the ms timestamp of the last reload on error
2476+ LAST_RELOADED_KEY = "reflex_last_reloaded_on_error"
2477+
2478+
24732479class FrontendEventExceptionState (State ):
24742480 """Substate for handling frontend exceptions."""
24752481
2482+ # If the frontend error message contains any of these strings, automatically reload the page.
2483+ auto_reload_on_errors : ClassVar [list [re .Pattern ]] = [
2484+ re .compile ( # Chrome/Edge
2485+ re .escape ("TypeError: Cannot read properties of null" )
2486+ ),
2487+ re .compile (re .escape ("TypeError: null is not an object" )), # Safari
2488+ re .compile (r"TypeError: can't access property \".*\" of null" ), # Firefox
2489+ ]
2490+
24762491 @event
2477- def handle_frontend_exception (self , info : str , component_stack : str ) -> None :
2492+ def handle_frontend_exception (
2493+ self , info : str , component_stack : str
2494+ ) -> Iterator [EventSpec ]:
24782495 """Handle frontend exceptions.
24792496
24802497 If a frontend exception handler is provided, it will be called.
@@ -2484,7 +2501,21 @@ def handle_frontend_exception(self, info: str, component_stack: str) -> None:
24842501 info: The exception information.
24852502 component_stack: The stack trace of the component where the exception occurred.
24862503
2504+ Yields:
2505+ Optional auto-reload event for certain errors outside cooldown period.
24872506 """
2507+ # Handle automatic reload for certain errors.
2508+ if type (self ).auto_reload_on_errors and any (
2509+ error .search (info ) for error in type (self ).auto_reload_on_errors
2510+ ):
2511+ yield call_script (
2512+ f"const last_reload = parseInt(window.sessionStorage.getItem('{ LAST_RELOADED_KEY } ')) || 0;"
2513+ f"if (Date.now() - last_reload > { environment .REFLEX_AUTO_RELOAD_COOLDOWN_TIME_MS .get ()} )"
2514+ "{"
2515+ f"window.sessionStorage.setItem('{ LAST_RELOADED_KEY } ', Date.now().toString());"
2516+ "window.location.reload();"
2517+ "}"
2518+ )
24882519 prerequisites .get_and_validate_app ().app .frontend_exception_handler (
24892520 Exception (info )
24902521 )
0 commit comments