Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 48x 49x 49x 48x 24x 1x 1x 1x 1x 1x 101x 49x 2x 47x 1x 52x 52x | import React, { Component, ReactNode } from "react";
/**
* Props for the ErrorBoundary component
*/
interface Props {
/** Child components to be wrapped by the error boundary */
readonly children: ReactNode;
/** Optional custom fallback UI to display instead of default error UI */
readonly fallback?: ReactNode;
}
/**
* State for the ErrorBoundary component
*/
interface State {
/** Whether an error has been caught */
readonly hasError: boolean;
/** The caught error object, null if no error */
readonly error: Error | null;
}
/**
* ErrorBoundary component to catch and display errors gracefully.
* Prevents black screen errors and provides user-friendly error UI with Korean/English bilingual support.
*
* @example
* ```tsx
* <ErrorBoundary>
* <App />
* </ErrorBoundary>
* ```
*/
export class ErrorBoundary extends Component<Props, State> {
private didRecover = false;
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error("ErrorBoundary caught error:", error, errorInfo);
}
/**
* Reset error state and attempt recovery without full page reload.
* Full reload is used as a last resort if recovery fails.
*/
private handleReset = () => {
// Mark as not recovered yet
this.didRecover = false;
// Try to recover by resetting error state
this.setState({ hasError: false, error: null });
// Give React a chance to re-render, then reload if recovery failed
setTimeout(() => {
Iif (!this.didRecover) {
window.location.reload();
}
}, 100);
};
render() {
if (this.state.hasError) {
if (this.props.fallback) {
return this.props.fallback;
}
return (
<div
className="error-boundary"
role="alert"
aria-live="assertive"
data-testid="error-boundary"
>
<div className="error-boundary__container">
<h1 className="error-boundary__title">
오류 발생 | Error Occurred
</h1>
<p className="error-boundary__message">
{this.state.error?.message ?? "Unknown error occurred"}
</p>
<div className="error-boundary__actions">
<button
type="button"
onClick={this.handleReset}
className="error-boundary__button error-boundary__button--primary"
data-testid="error-boundary-restart-button"
>
다시 시작 | Restart
</button>
<button
type="button"
onClick={() => window.history.back()}
className="error-boundary__button error-boundary__button--secondary"
data-testid="error-boundary-back-button"
>
뒤로 | Back
</button>
</div>
{process.env.NODE_ENV === "development" && this.state.error && (
<details className="error-boundary__details">
<summary>기술 정보 | Technical Details</summary>
<pre>{this.state.error.stack}</pre>
</details>
)}
</div>
</div>
);
}
// Mark recovery as successful when rendering children
this.didRecover = true;
return this.props.children;
}
}
|