Show a crash outside a page instead of a white screen
Moving between pages sometimes left a white screen until a reload: an error outside the page's own error boundary (the layout, the sign-in gate) unmounted the whole app. An error boundary now wraps the whole app, shows the error's name and message, and tries again when the route changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,10 +3,15 @@ import { t } from '../i18n'
|
||||
import { Empty } from './Page'
|
||||
|
||||
// Without this, one component throwing while rendering unmounts the whole app and leaves a white
|
||||
// page. The layout keys it by route, so moving to another page clears the error.
|
||||
export class ErrorBoundary extends Component<{ children: ReactNode }, { error: Error | null }> {
|
||||
// page. The layout keys it by route, so moving to another page clears the error; main.tsx also puts
|
||||
// one around the whole app (the layout included), cleared by a change of `resetKey`.
|
||||
export class ErrorBoundary extends Component<{ children: ReactNode; resetKey?: string; className?: string }, { error: Error | null }> {
|
||||
state = { error: null as Error | null }
|
||||
|
||||
componentDidUpdate(prev: { resetKey?: string }) {
|
||||
if (this.state.error && prev.resetKey !== this.props.resetKey) this.setState({ error: null })
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error) {
|
||||
return { error }
|
||||
}
|
||||
@@ -19,11 +24,11 @@ export class ErrorBoundary extends Component<{ children: ReactNode }, { error: E
|
||||
const { error } = this.state
|
||||
if (!error) return this.props.children
|
||||
return (
|
||||
<div className="card">
|
||||
<div className={this.props.className ?? 'card'}>
|
||||
<Empty icon="info" title={t('err.crashTitle')}>
|
||||
{t('err.crashCopy')}
|
||||
<br />
|
||||
<small>{error.message}</small>
|
||||
<small>{error.name}: {error.message}</small>
|
||||
</Empty>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', gap: 8, paddingBottom: 24 }}>
|
||||
<button className="btn small" onClick={() => this.setState({ error: null })}>{t('common.retry')}</button>
|
||||
|
||||
Reference in New Issue
Block a user