|
@@ -8,13 +8,24 @@ import {t} from 'app/locale';
|
|
|
import Alert from 'app/components/alert';
|
|
|
import DetailedError from 'app/components/errors/detailedError';
|
|
|
|
|
|
-const exclamation = ['Raspberries', 'Snap', 'Frig', 'Welp', 'Uhhhh', 'Hmmm'];
|
|
|
+type Props = {
|
|
|
+ mini?: boolean;
|
|
|
+ message?: React.ReactNode;
|
|
|
+ customComponent?: React.ReactNode;
|
|
|
+ className?: string;
|
|
|
+};
|
|
|
|
|
|
-const getExclamation = () => {
|
|
|
- return exclamation[Math.floor(Math.random() * exclamation.length)];
|
|
|
+type State = {
|
|
|
+ error: Error | null;
|
|
|
};
|
|
|
|
|
|
-class ErrorBoundary extends React.Component {
|
|
|
+const exclamation = ['Raspberries', 'Snap', 'Frig', 'Welp', 'Uhhhh', 'Hmmm'] as const;
|
|
|
+
|
|
|
+function getExclamation() {
|
|
|
+ return exclamation[Math.floor(Math.random() * exclamation.length)];
|
|
|
+}
|
|
|
+
|
|
|
+class ErrorBoundary extends React.Component<Props, State> {
|
|
|
static propTypes = {
|
|
|
mini: PropTypes.bool,
|
|
|
message: PropTypes.node,
|
|
@@ -25,10 +36,12 @@ class ErrorBoundary extends React.Component {
|
|
|
mini: false,
|
|
|
};
|
|
|
|
|
|
- constructor(props) {
|
|
|
- super(props);
|
|
|
- this.state = {error: null};
|
|
|
- }
|
|
|
+ state: State = {
|
|
|
+ error: null,
|
|
|
+ };
|
|
|
+
|
|
|
+ // XXX: browserHistory.listen does not have a correct return type.
|
|
|
+ unlistenBrowserHistory: any;
|
|
|
|
|
|
componentDidMount() {
|
|
|
// Listen for route changes so we can clear error
|
|
@@ -37,7 +50,7 @@ class ErrorBoundary extends React.Component {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- componentDidCatch(error, errorInfo) {
|
|
|
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
|
this.setState({error});
|
|
|
Sentry.withScope(scope => {
|
|
|
scope.setExtra('errorInfo', errorInfo);
|
|
@@ -52,38 +65,40 @@ class ErrorBoundary extends React.Component {
|
|
|
}
|
|
|
|
|
|
render() {
|
|
|
- if (this.state.error) {
|
|
|
- const {customComponent, mini, message, className} = this.props;
|
|
|
+ const {error} = this.state;
|
|
|
+
|
|
|
+ if (!error) {
|
|
|
+ //when there's not an error, render children untouched
|
|
|
+ return this.props.children;
|
|
|
+ }
|
|
|
|
|
|
- if (customComponent) {
|
|
|
- return customComponent;
|
|
|
- }
|
|
|
+ const {customComponent, mini, message, className} = this.props;
|
|
|
|
|
|
- if (mini) {
|
|
|
- return (
|
|
|
- <Alert type="error" icon="icon-circle-exclamation" className={className}>
|
|
|
- {message || t('There was a problem rendering this component')}
|
|
|
- </Alert>
|
|
|
- );
|
|
|
- }
|
|
|
+ if (customComponent) {
|
|
|
+ return customComponent;
|
|
|
+ }
|
|
|
|
|
|
+ if (mini) {
|
|
|
return (
|
|
|
- <Wrapper>
|
|
|
- <DetailedError
|
|
|
- heading={getExclamation()}
|
|
|
- message={t(
|
|
|
- `Something went horribly wrong rendering this page.
|
|
|
-We use a decent error reporting service so this will probably be fixed soon. Unless our error reporting service is also broken. That would be awkward.
|
|
|
-Anyway, we apologize for the inconvenience.`
|
|
|
- )}
|
|
|
- />
|
|
|
- <StackTrace>{this.state.error.toString()}</StackTrace>
|
|
|
- </Wrapper>
|
|
|
+ <Alert type="error" icon="icon-circle-exclamation" className={className}>
|
|
|
+ {message || t('There was a problem rendering this component')}
|
|
|
+ </Alert>
|
|
|
);
|
|
|
- } else {
|
|
|
- //when there's not an error, render children untouched
|
|
|
- return this.props.children;
|
|
|
}
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Wrapper>
|
|
|
+ <DetailedError
|
|
|
+ heading={getExclamation()}
|
|
|
+ message={t(
|
|
|
+ `Something went horribly wrong rendering this page.
|
|
|
+We use a decent error reporting service so this will probably be fixed soon. Unless our error reporting service is also broken. That would be awkward.
|
|
|
+Anyway, we apologize for the inconvenience.`
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ <StackTrace>{error.toString()}</StackTrace>
|
|
|
+ </Wrapper>
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|