error_boundary.py 2.5 KB

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