/**
* ErrorBoundary.jsx
* ==================
* React Error Boundary component that catches render-phase errors
* and displays a fallback UI instead of crashing the entire app.
*
* Two boundary levels are used in the app:
* 1. SchemaErrorBoundary — wraps DynamicClinicalForm (schema fetch failures)
* 2. GlobalErrorBoundary — wraps the entire DiseaseProvider subtree
*/
import { Component } from 'react';
import SchemaErrorFallback from './SchemaErrorFallback';
/**
* Generic Error Boundary with configurable fallback.
*
* Usage:
* }
* onError={(error, info) => console.error(error, info)}
* >
*
*
*/
export default class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, info) {
// Log to console (or external service in production)
console.error('[ErrorBoundary] Caught error:', error);
if (info?.componentStack) {
console.error('[ErrorBoundary] Component stack:', info.componentStack);
}
// Call optional onError prop
if (this.props.onError) {
this.props.onError(error, info);
}
}
handleRetry = () => {
this.setState({ hasError: false, error: null });
};
render() {
if (this.state.hasError) {
// Use custom fallback if provided, otherwise default
if (this.props.fallback) {
return typeof this.props.fallback === 'function'
? this.props.fallback({
error: this.state.error,
retry: this.handleRetry,
})
: this.props.fallback;
}
// Default fallback
return (
);
}
return this.props.children;
}
}
/**
* SchemaErrorBoundary — pre-configured for schema-related errors.
* Includes a disease prop for context in the fallback UI.
*/
export function SchemaErrorBoundary({ children, disease }) {
return (
(
)}
>
{children}
);
}