diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2019-03-15 05:35:45 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-15 05:35:45 +0100 |
commit | c20d096e6a251e1b84ac47b751d2eb065743dbc2 (patch) | |
tree | f3e9fa961ba9170e1a70b3854bbe0711ec560b2f /app/javascript | |
parent | ff565524aa6aa35c07557ea02d8d04bb3a9e1a97 (diff) |
Show disappointed elephant if web UI crashes (#10275)
* Do not crash the whole UI when loading an invalid column * Add error boundary component to catch Web UI crashes * Add stack trace on supported browsers * Add component stack info, pre-format everything for github * Make “Reload” a clickable link that calls window.location.reload() * Remove elephant friend from error boundary, make title stand out more * Simplify error boundary to only a graphic
Diffstat (limited to 'app/javascript')
-rw-r--r-- | app/javascript/mastodon/components/error_boundary.js | 39 | ||||
-rw-r--r-- | app/javascript/mastodon/containers/mastodon.js | 5 | ||||
-rw-r--r-- | app/javascript/mastodon/features/ui/components/bundle.js | 5 |
3 files changed, 48 insertions, 1 deletions
diff --git a/app/javascript/mastodon/components/error_boundary.js b/app/javascript/mastodon/components/error_boundary.js new file mode 100644 index 000000000..d1ca5bf75 --- /dev/null +++ b/app/javascript/mastodon/components/error_boundary.js @@ -0,0 +1,39 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import illustration from '../../images/elephant_ui_disappointed.svg'; + +export default class ErrorBoundary extends React.PureComponent { + + static propTypes = { + children: PropTypes.node, + }; + + state = { + hasError: false, + stackTrace: undefined, + componentStack: undefined, + } + + componentDidCatch(error, info) { + this.setState({ + hasError: true, + stackTrace: error.stack, + componentStack: info && info.componentStack, + }); + } + + render() { + const { hasError } = this.state; + + if (!hasError) { + return this.props.children; + } + + return ( + <div> + <img src={illustration} alt='' /> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js index 2912540a0..542b68282 100644 --- a/app/javascript/mastodon/containers/mastodon.js +++ b/app/javascript/mastodon/containers/mastodon.js @@ -13,6 +13,7 @@ import { connectUserStream } from '../actions/streaming'; import { IntlProvider, addLocaleData } from 'react-intl'; import { getLocale } from '../locales'; import initialState from '../initial_state'; +import ErrorBoundary from '../components/error_boundary'; const { localeData, messages } = getLocale(); addLocaleData(localeData); @@ -75,7 +76,9 @@ export default class Mastodon extends React.PureComponent { return ( <IntlProvider locale={locale} messages={messages}> <Provider store={store}> - <MastodonMount /> + <ErrorBoundary> + <MastodonMount /> + </ErrorBoundary> </Provider> </IntlProvider> ); diff --git a/app/javascript/mastodon/features/ui/components/bundle.js b/app/javascript/mastodon/features/ui/components/bundle.js index e7d935251..a60ace35b 100644 --- a/app/javascript/mastodon/features/ui/components/bundle.js +++ b/app/javascript/mastodon/features/ui/components/bundle.js @@ -53,6 +53,11 @@ class Bundle extends React.PureComponent { const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props; const cachedMod = Bundle.cache.get(fetchComponent); + if (fetchComponent === undefined) { + this.setState({ mod: null }); + return Promise.resolve(); + } + onFetch(); if (cachedMod) { |