diff --git a/src/components/RavenBoundary.js b/src/components/RavenBoundary.js new file mode 100644 index 0000000..dc25ac4 --- /dev/null +++ b/src/components/RavenBoundary.js @@ -0,0 +1,43 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import RavenError from './RavenError'; + +class RavenBoundary extends React.Component { + constructor() { + super(); + this.state = { + error: null + }; + } + + componentDidCatch(error, errorInfo) { + this.setState({ error, errorInfo }); + } + + render() { + const { error, errorInfo } = this.state; + const { children } = this.props; + + if (error) { + const errorProps = { + heading: 'An error has occurred.', + details: { extra: errorInfo }, + error + }; + + return ; + } else { + return children; + } + } +} + +RavenBoundary.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]).isRequired +}; + +export default RavenBoundary; diff --git a/src/components/RavenError.js b/src/components/RavenError.js new file mode 100644 index 0000000..b76ed9c --- /dev/null +++ b/src/components/RavenError.js @@ -0,0 +1,37 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Raven } from '../sentry'; + +import Message from './Message'; +import AlertIcon from 'feather-icons/dist/icons/alert-octagon.svg'; + +class RavenError extends React.Component { + componentDidMount() { + const { error, details } = this.props; + Raven.captureException(error, details); + } + + reportError = event => { + event.preventDefault(); + + if (Raven.lastEventId()) { + Raven.showReportDialog(); + } + } + + render() { + const { heading } = this.props; + + return +

This error has been logged. You may also fill out a report.

+
; + } +} + +RavenError.propTypes = { + error: PropTypes.object.isRequired, + details: PropTypes.object.isRequired, + heading: PropTypes.string.isRequired +}; + +export default RavenError; diff --git a/src/pages/index/index.js b/src/pages/index/index.js index 609998d..5593cb9 100644 --- a/src/pages/index/index.js +++ b/src/pages/index/index.js @@ -2,16 +2,27 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from '../../components/App'; +import RavenBoundary from '../../components/RavenBoundary'; import '../../style.css'; import { setupServiceWorker } from '../../service-worker'; import { setupGA } from '../../analytics'; -import { setupRaven } from '../../sentry'; +import { Raven, setupRaven } from '../../sentry'; setupRaven(); -setupGA(); -if (process.env.NODE_ENV === 'production') { - setupServiceWorker(); -} -ReactDOM.render(, document.getElementById('root')); +try { + setupGA(); + if (process.env.NODE_ENV === 'production') { + setupServiceWorker(); + } + + ReactDOM.render( + + + , + document.getElementById('root')); +} +catch (e) { + Raven.captureException(e); +} diff --git a/src/sentry.js b/src/sentry.js index 9c3bf47..73faa96 100644 --- a/src/sentry.js +++ b/src/sentry.js @@ -9,4 +9,4 @@ const setupRaven = () => { }); }; -export { setupRaven }; +export { Raven, setupRaven };