Add ErrorBoundary class component with retry support
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
import { Component } from "react";
|
||||||
|
import type { ReactNode, ErrorInfo } from "react";
|
||||||
|
|
||||||
|
export interface ErrorBoundaryProps {
|
||||||
|
children: ReactNode;
|
||||||
|
fallback?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrorBoundaryState {
|
||||||
|
hasError: boolean;
|
||||||
|
error: Error | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React error boundary that catches render-time exceptions in the subtree.
|
||||||
|
* Displays a minimal fallback UI with a "Retry" button that resets state.
|
||||||
|
*
|
||||||
|
* Must be a class component — React requires componentDidCatch / getDerivedStateFromError.
|
||||||
|
*/
|
||||||
|
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||||
|
override state: ErrorBoundaryState = { hasError: false, error: null };
|
||||||
|
|
||||||
|
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||||
|
return { hasError: true, error };
|
||||||
|
}
|
||||||
|
|
||||||
|
override componentDidCatch(error: Error, info: ErrorInfo): void {
|
||||||
|
// Phase 1G-logger will replace this with useLogger() context logging.
|
||||||
|
// For now, write to console so errors are not silently swallowed.
|
||||||
|
console.error("[ErrorBoundary]", error, info.componentStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly handleRetry = (): void => {
|
||||||
|
this.setState({ hasError: false, error: null });
|
||||||
|
};
|
||||||
|
|
||||||
|
override render(): ReactNode {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
if (this.props.fallback) {
|
||||||
|
return this.props.fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div role="alert">
|
||||||
|
<h2>Something went wrong</h2>
|
||||||
|
<p>{this.state.error?.message}</p>
|
||||||
|
<button type="button" onClick={this.handleRetry}>
|
||||||
|
Retry
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user