Improve error boundary in inspected elements panel (#21531)

Show more info about the error as well as the option to report it to GitHub.
This commit is contained in:
Brian Vaughn
2021-05-19 13:27:56 -04:00
committed by GitHub
parent fa8f73c1d6
commit dfb8ebf078
3 changed files with 21 additions and 97 deletions
@@ -1,21 +1,3 @@
.Error {
justify-content: center;
align-items: center;
display: flex;
flex-direction: column;
height: 100%;
font-size: var(--font-size-sans-large);
font-weight: bold;
text-align: center;
background-color: var(--color-error-background);
color: var(--color-error-text);
border: 1px solid var(--color-error-border);
padding: 1rem;
}
.Message {
margin-bottom: 1rem;
}
.RetryButton {
.Wrapper {
border-left: 1px solid var(--color-border);
}
@@ -8,13 +8,9 @@
*/
import * as React from 'react';
import {Component, useContext} from 'react';
import {TreeDispatcherContext} from './TreeContext';
import Button from 'react-devtools-shared/src/devtools/views/Button';
import ErrorBoundary from '../ErrorBoundary';
import styles from './InspectedElementErrorBoundary.css';
import type {DispatcherContext} from './InspectedElementErrorBoundary.css';
type WrapperProps = {|
children: React$Node,
|};
@@ -22,72 +18,9 @@ type WrapperProps = {|
export default function InspectedElementErrorBoundaryWrapper({
children,
}: WrapperProps) {
const dispatch = useContext(TreeDispatcherContext);
return (
<InspectedElementErrorBoundary children={children} dispatch={dispatch} />
<div className={styles.Wrapper}>
<ErrorBoundary canDismiss={true}>{children}</ErrorBoundary>
</div>
);
}
type Props = {|
children: React$Node,
dispatch: DispatcherContext,
|};
type State = {|
errorMessage: string | null,
hasError: boolean,
|};
const InitialState: State = {
errorMessage: null,
hasError: false,
};
class InspectedElementErrorBoundary extends Component<Props, State> {
state: State = InitialState;
static getDerivedStateFromError(error: any) {
const errorMessage =
typeof error === 'object' &&
error !== null &&
error.hasOwnProperty('message')
? error.message
: error;
return {
errorMessage,
hasError: true,
};
}
render() {
const {children} = this.props;
const {errorMessage, hasError} = this.state;
if (hasError) {
return (
<div className={styles.Error}>
<div className={styles.Message}>{errorMessage || 'Error'}</div>
<Button className={styles.RetryButton} onClick={this._retry}>
Dismiss
</Button>
</div>
);
}
return children;
}
_retry = () => {
const {dispatch} = this.props;
dispatch({
type: 'SELECT_ELEMENT_BY_ID',
payload: null,
});
this.setState({
errorMessage: null,
hasError: false,
});
};
}
@@ -16,7 +16,8 @@ import SuspendingErrorView from './SuspendingErrorView';
type Props = {|
children: React$Node,
store: Store,
canDismiss?: boolean,
store?: Store,
|};
type State = {|
@@ -70,18 +71,24 @@ export default class ErrorBoundary extends Component<Props, State> {
}
componentDidMount() {
this.props.store.addListener('error', this._onStoreError);
const {store} = this.props;
if (store != null) {
store.addListener('error', this._onStoreError);
}
}
componentWillUnmount() {
this.props.store.removeListener('error', this._onStoreError);
const {store} = this.props;
if (store != null) {
store.removeListener('error', this._onStoreError);
}
}
render() {
const {children} = this.props;
const {canDismiss: canDismissProp, children} = this.props;
const {
callStack,
canDismiss,
canDismiss: canDismissState,
componentStack,
errorMessage,
hasError,
@@ -92,7 +99,9 @@ export default class ErrorBoundary extends Component<Props, State> {
<ErrorView
callStack={callStack}
componentStack={componentStack}
dismissError={canDismiss ? this._dismissError : null}
dismissError={
canDismissProp || canDismissState ? this._dismissError : null
}
errorMessage={errorMessage}>
<Suspense fallback={<SearchingGitHubIssues />}>
<SuspendingErrorView