-
Notifications
You must be signed in to change notification settings - Fork 202
Expand file tree
/
Copy pathErrorBoundary.tsx
More file actions
118 lines (107 loc) · 3.2 KB
/
Copy pathErrorBoundary.tsx
File metadata and controls
118 lines (107 loc) · 3.2 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
import { Component, ErrorInfo, ReactNode } from "react";
import { Link } from "react-router-dom";
import "../pages/ErrorPage.css";
interface Props {
/** Application subtree to guard. */
children: ReactNode;
}
interface State {
/** True after an error was thrown by a descendant render. */
hasError: boolean;
/** The error that was thrown, if any — used to render diagnostic info. */
error?: Error;
}
/**
* Top-level render-error boundary, mounted as the outermost wrapper in
* `src/App.tsx`.
*
* Catches any error thrown during render in the subtree and renders the
* fallback `ErrorPage` instead of letting React unmount the root. The
* original error is captured into local state for display and logged to
* the console in `componentDidCatch`.
*
* Why a class component: React still requires error boundaries to be
* class components. There is no hook equivalent today.
*
* Does NOT catch:
* - errors thrown in event handlers (use try/catch locally)
* - errors thrown asynchronously after render (e.g. `setTimeout`)
* - errors thrown inside the boundary's own render
*/
export class ErrorBoundary extends Component<Props, State> {
public state: State = {
hasError: false,
};
public static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("Uncaught error:", error, errorInfo);
}
public render() {
if (this.state.hasError) {
return <ErrorPage error={this.state.error} />;
}
return this.props.children;
}
}
interface ErrorPageProps {
error?: Error;
}
function ErrorPage({ error }: ErrorPageProps) {
const handleGoBack = () => {
window.history.back();
};
const handleReload = () => {
window.location.reload();
};
return (
<div className="error-page">
<div className="error-content">
<div className="error-icon" aria-hidden="true">
⚠️
</div>
<h1 className="error-title">Something went wrong</h1>
<p className="error-message">
We encountered an unexpected error. Our team has been notified and is
working to fix it.
</p>
{!error && (
<p className="error-details">
If this problem persists, please contact our support team.
</p>
)}
<div className="error-actions">
<button
className="error-btn error-btn-primary"
onClick={handleGoBack}
aria-label="Go back to previous page"
>
Go Back
</button>
<Link
to="/"
className="error-btn error-btn-secondary"
aria-label="Return to dashboard"
>
Dashboard
</Link>
<button
className="error-btn error-btn-secondary"
onClick={handleReload}
aria-label="Reload the page"
>
Reload Page
</button>
<a
href="mailto:support@creditra.com"
className="error-btn error-btn-secondary"
aria-label="Contact support via email"
>
Contact Support
</a>
</div>
</div>
</div>
);
}