First Commit
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { api } from "../api";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
type State = {
|
||||
hasError: boolean;
|
||||
errorId?: string;
|
||||
};
|
||||
|
||||
export default class ErrorBoundary extends React.Component<Props, State> {
|
||||
state: State = { hasError: false };
|
||||
|
||||
static getDerivedStateFromError(_: any) {
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error: any, info: any) {
|
||||
const errorId = `ui_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
||||
this.setState({ errorId });
|
||||
|
||||
// Best-effort: report to API. If offline/misconfigured, we still show fallback UI.
|
||||
void api.post("/client-errors", {
|
||||
errorId,
|
||||
message: String(error?.message ?? error),
|
||||
stack: String(error?.stack ?? ""),
|
||||
componentStack: String(info?.componentStack ?? ""),
|
||||
url: window.location.href,
|
||||
userAgent: navigator.userAgent,
|
||||
at: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.hasError) return this.props.children;
|
||||
|
||||
return (
|
||||
<div style={{ padding: 24, maxWidth: 820, margin: "0 auto" }}>
|
||||
<h2 style={{ margin: "0 0 8px 0" }}>Something crashed.</h2>
|
||||
<div style={{ opacity: 0.8, marginBottom: 16 }}>
|
||||
Try refreshing. If it keeps happening, capture this ID:
|
||||
<div style={{ fontFamily: "monospace", marginTop: 6 }}>
|
||||
{this.state.errorId ?? "unknown"}
|
||||
</div>
|
||||
</div>
|
||||
<button onClick={() => window.location.reload()}>Refresh</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user