import React, { useState } from 'react'; import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import i18n from 'i18next'; import Modal from '../Modal'; import Icon from '../Icon'; import IconButton from '../IconButton'; const isProduction = process.env.NODE_ENV === 'production'; const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute }) => { const { t } = useTranslation('ErrorBoundary'); const [showDetails, setShowDetails] = useState(false); const title = `${t('Something went wrong')}${!isProduction && ` ${t('in')} ${context}`}.`; const subtitle = t('Sorry, something went wrong there. Try again.'); return (

{title}

{subtitle}

{!isProduction && (

{t('Context')}: {context}

{t('Error Message')}: {error.message}

setShowDetails(!showDetails)} >
{t('Stack Trace')}
{showDetails &&

Stack: {error.stack}

}
)}
); }; const noop = () => {}; DefaultFallback.propTypes = { error: PropTypes.object.isRequired, resetErrorBoundary: PropTypes.func, componentStack: PropTypes.string, }; DefaultFallback.defaultProps = { resetErrorBoundary: noop, }; const ErrorBoundary = ({ context, onReset, onError, fallbackComponent: FallbackComponent, children, fallbackRoute, isPage, }) => { const [isOpen, setIsOpen] = useState(true); const onErrorHandler = (error, componentStack) => { console.error(`${context} Error Boundary`, error, componentStack, context); onError(error, componentStack, context); }; const onResetHandler = (...args) => onReset(...args); const withModal = Component => props => ( { setIsOpen(false); if (fallbackRoute && typeof window !== 'undefined') { window.location = fallbackRoute; } }} > ); const Fallback = isPage ? FallbackComponent : withModal(FallbackComponent); return ( ( )} onReset={onResetHandler} onError={onErrorHandler} > {children} ); }; ErrorBoundary.propTypes = { context: PropTypes.string, onReset: PropTypes.func, onError: PropTypes.func, fallbackComponent: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), children: PropTypes.node.isRequired, fallbackRoute: PropTypes.string, }; ErrorBoundary.defaultProps = { context: 'OHIF', onReset: noop, onError: noop, fallbackComponent: DefaultFallback, fallbackRoute: null, }; export default ErrorBoundary;