aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/client/components/ErrorBoundary.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/components/ErrorBoundary.tsx')
-rw-r--r--src/client/components/ErrorBoundary.tsx42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/client/components/ErrorBoundary.tsx b/src/client/components/ErrorBoundary.tsx
new file mode 100644
index 0000000..a86ea9a
--- /dev/null
+++ b/src/client/components/ErrorBoundary.tsx
@@ -0,0 +1,42 @@
+import { Component, type ReactNode } from "react";
+
+interface ErrorBoundaryProps {
+ children: ReactNode;
+ fallback?: ReactNode;
+}
+
+interface ErrorBoundaryState {
+ hasError: boolean;
+ error: Error | null;
+}
+
+export class ErrorBoundary extends Component<
+ ErrorBoundaryProps,
+ ErrorBoundaryState
+> {
+ override state: ErrorBoundaryState = { hasError: false, error: null };
+
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
+ return { hasError: true, error };
+ }
+
+ override render() {
+ if (this.state.hasError) {
+ return this.props.fallback ?? <ErrorFallback error={this.state.error} />;
+ }
+ return this.props.children;
+ }
+}
+
+function ErrorFallback({ error }: { error: Error | null }) {
+ return (
+ <div
+ role="alert"
+ className="bg-error/5 border border-error/20 rounded-xl p-4"
+ >
+ <span className="text-error">
+ {error?.message ?? "An error occurred"}
+ </span>
+ </div>
+ );
+}