forked from Movalabs-crew/mova-store
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathErrorBoundary.tsx
More file actions
148 lines (129 loc) · 4.12 KB
/
Copy pathErrorBoundary.tsx
File metadata and controls
148 lines (129 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"use client";
import React, { Component, ErrorInfo, ReactNode } from "react";
import { MdError, MdRefresh, MdHome } from "react-icons/md";
import Link from "next/link";
interface Props {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, errorInfo: ErrorInfo) => void;
}
interface State {
hasError: boolean;
error: Error | null;
errorInfo: ErrorInfo | null;
}
/**
* Error Boundary Component
*
* Catches JavaScript errors anywhere in the child component tree,
* logs those errors, and displays a fallback UI.
*
* Usage:
* ```tsx
* <ErrorBoundary>
* <YourComponent />
* </ErrorBoundary>
* ```
*/
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null,
};
}
static getDerivedStateFromError(error: Error): Partial<State> {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.setState({ errorInfo });
// Log to console in development
if (process.env.NODE_ENV === "development") {
console.error("ErrorBoundary caught an error:", error);
console.error("Component stack:", errorInfo.componentStack);
}
// Call optional error handler
this.props.onError?.(error, errorInfo);
// Here you could also log to an error reporting service like Sentry
// logErrorToService(error, errorInfo);
}
handleReset = () => {
this.setState({
hasError: false,
error: null,
errorInfo: null,
});
};
render() {
if (this.state.hasError) {
// Custom fallback UI
if (this.props.fallback) {
return this.props.fallback;
}
// Default error UI
return (
<div className="min-h-[400px] flex items-center justify-center p-8">
<div className="max-w-md w-full text-center">
<div className="mx-auto w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mb-6">
<MdError className="w-8 h-8 text-red-500" />
</div>
<h2 className="text-2xl font-bold text-gray-800 mb-2">
Something went wrong
</h2>
<p className="text-gray-600 mb-6">
We're sorry, but something unexpected happened. Please try refreshing
the page or go back to the home page.
</p>
{process.env.NODE_ENV === "development" && this.state.error && (
<details className="text-left mb-6 p-4 bg-gray-100 rounded-lg">
<summary className="cursor-pointer text-sm font-medium text-gray-700">
Error Details (Development Only)
</summary>
<pre className="mt-2 text-xs text-red-600 overflow-auto max-h-40">
{this.state.error.toString()}
{this.state.errorInfo?.componentStack}
</pre>
</details>
)}
<div className="flex gap-4 justify-center">
<button
onClick={this.handleReset}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
<MdRefresh className="w-5 h-5" />
Try Again
</button>
<Link
href="/"
className="flex items-center gap-2 px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors"
>
<MdHome className="w-5 h-5" />
Go Home
</Link>
</div>
</div>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
/**
* Hook-based error boundary wrapper for functional components.
* Use this to wrap specific parts of your UI.
*/
export function withErrorBoundary<P extends object>(
WrappedComponent: React.ComponentType<P>,
fallback?: ReactNode
) {
return function WithErrorBoundary(props: P) {
return (
<ErrorBoundary fallback={fallback}>
<WrappedComponent {...props} />
</ErrorBoundary>
);
};
}