Spaces:
Running
Running
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import CrashMessageComponent from '../components/crash-message/crash-message.jsx'; | |
import log from '../lib/log.js'; | |
import {recommendedBrowser} from '../lib/supported-browser'; | |
class ErrorBoundary extends React.Component { | |
constructor (props) { | |
super(props); | |
this.state = { | |
hasError: false, | |
errorId: null | |
}; | |
} | |
componentDidCatch (error, info) { | |
// Error object may be undefined (IE?) | |
error = error || { | |
stack: 'Unknown stack', | |
message: 'Unknown error' | |
}; | |
// Log errors to analytics, leaving out browsers that are not in our recommended set | |
if (recommendedBrowser() && window.Sentry) { | |
window.Sentry.withScope(scope => { | |
Object.keys(info).forEach(key => { | |
scope.setExtra(key, info[key]); | |
}); | |
scope.setExtra('action', this.props.action); | |
window.Sentry.captureException(error); | |
}); | |
} | |
// Display fallback UI | |
this.setState({ | |
hasError: true, | |
errorId: window.Sentry ? window.Sentry.lastEventId() : null, | |
errorMessage: `${(error && error.message) || error}` | |
}); | |
// Log error locally for debugging as well. | |
log.error(`Unhandled Error: ${error.stack ? error.stack : error}\nComponent stack: ${info.componentStack}`); | |
} | |
handleBack () { | |
window.history.back(); | |
} | |
handleReload () { | |
window.location.replace(window.location.origin + window.location.pathname); | |
} | |
render () { | |
if (this.state.hasError) { | |
return ( | |
<CrashMessageComponent | |
eventId={this.state.errorId} | |
errorMessage={this.state.errorMessage} | |
onReload={this.handleReload} | |
/> | |
); | |
} | |
return this.props.children; | |
} | |
} | |
ErrorBoundary.propTypes = { | |
action: PropTypes.string.isRequired, // Used for defining tracking action | |
children: PropTypes.node | |
}; | |
export default ErrorBoundary; | |