error_boundary.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. """A React Error Boundary component that catches unhandled frontend exceptions."""
  2. from __future__ import annotations
  3. from typing import Dict, List, Tuple
  4. from reflex.compiler.compiler import _compile_component
  5. from reflex.components.component import Component
  6. from reflex.components.el import div, p
  7. from reflex.event import EventHandler
  8. from reflex.state import FrontendEventExceptionState
  9. from reflex.vars.base import Var
  10. def on_error_spec(
  11. error: Var[Dict[str, str]], info: Var[Dict[str, str]]
  12. ) -> Tuple[Var[str], Var[str]]:
  13. """The spec for the on_error event handler.
  14. Args:
  15. error: The error message.
  16. info: Additional information about the error.
  17. Returns:
  18. The arguments for the event handler.
  19. """
  20. return (
  21. error.stack,
  22. info.componentStack,
  23. )
  24. class ErrorBoundary(Component):
  25. """A React Error Boundary component that catches unhandled frontend exceptions."""
  26. library = "react-error-boundary"
  27. tag = "ErrorBoundary"
  28. # Fired when the boundary catches an error.
  29. on_error: EventHandler[on_error_spec]
  30. # Rendered instead of the children when an error is caught.
  31. Fallback_component: Var[Component] = Var(_js_expr="Fallback")._replace(
  32. _var_type=Component
  33. )
  34. def add_custom_code(self) -> List[str]:
  35. """Add custom Javascript code into the page that contains this component.
  36. Custom code is inserted at module level, after any imports.
  37. Returns:
  38. The custom code to add.
  39. """
  40. fallback_container = div(
  41. p("Ooops...Unknown Reflex error has occured:"),
  42. p(
  43. Var(_js_expr="error.message"),
  44. color="red",
  45. ),
  46. p("Please contact the support."),
  47. )
  48. compiled_fallback = _compile_component(fallback_container)
  49. return [
  50. f"""
  51. function Fallback({{ error, resetErrorBoundary }}) {{
  52. return (
  53. {compiled_fallback}
  54. );
  55. }}
  56. """
  57. ]
  58. @classmethod
  59. def create(cls, *children, **props):
  60. """Create an ErrorBoundary component.
  61. Args:
  62. *children: The children of the component.
  63. **props: The props of the component.
  64. Returns:
  65. The ErrorBoundary component.
  66. """
  67. if "on_error" not in props:
  68. props["on_error"] = FrontendEventExceptionState.handle_frontend_exception
  69. return super().create(*children, **props)
  70. error_boundary = ErrorBoundary.create