Improve error boundary in inspected elements panel (#21531)
Show more info about the error as well as the option to report it to GitHub.
Brian Vaughn committed
May 19, 2021 at 10:27 UTC
99995c1063d1a9d3bfbcdf41078cb1e685218d99
3 files changed
+21
-97
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorBoundary.css
+2
-20
@@ -1,21 +1,3 @@
1
-.Error {
2
- justify-content: center;
3
- align-items: center;
4
- display: flex;
5
- flex-direction: column;
6
- height: 100%;
7
- font-size: var(--font-size-sans-large);
8
- font-weight: bold;
9
- text-align: center;
10
- background-color: var(--color-error-background);
11
- color: var(--color-error-text);
12
- border: 1px solid var(--color-error-border);
13
- padding: 1rem;
14
-}
15
-
16
-.Message {
17
- margin-bottom: 1rem;
18
-}
19
-
20
-.RetryButton {
1
+.Wrapper {
2
+ border-left: 1px solid var(--color-border);
3
}
\ No newline at end of file
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorBoundary.js
+4
-71
@@ -8,13 +8,9 @@
8
*/
9
10
import * as React from 'react';
11
-import {Component, useContext} from 'react';
12
-import {TreeDispatcherContext} from './TreeContext';
13
-import Button from 'react-devtools-shared/src/devtools/views/Button';
11
+import ErrorBoundary from '../ErrorBoundary';
12
import styles from './InspectedElementErrorBoundary.css';
13
16
-import type {DispatcherContext} from './InspectedElementErrorBoundary.css';
17
-
14
type WrapperProps = {|
15
children: React$Node,
16
|};
@@ -22,72 +18,9 @@ type WrapperProps = {|
18
export default function InspectedElementErrorBoundaryWrapper({
19
children,
20
}: WrapperProps) {
25
- const dispatch = useContext(TreeDispatcherContext);
26
-
21
return (
28
- <InspectedElementErrorBoundary children={children} dispatch={dispatch} />
22
+ <div className={styles.Wrapper}>
23
+ <ErrorBoundary canDismiss={true}>{children}</ErrorBoundary>
24
+ </div>
25
);
26
}
31
-
32
-type Props = {|
33
- children: React$Node,
34
- dispatch: DispatcherContext,
35
-|};
36
-
37
-type State = {|
38
- errorMessage: string | null,
39
- hasError: boolean,
40
-|};
41
-
42
-const InitialState: State = {
43
- errorMessage: null,
44
- hasError: false,
45
-};
46
-
47
-class InspectedElementErrorBoundary extends Component<Props, State> {
48
- state: State = InitialState;
49
-
50
- static getDerivedStateFromError(error: any) {
51
- const errorMessage =
52
- typeof error === 'object' &&
53
- error !== null &&
54
- error.hasOwnProperty('message')
55
- ? error.message
56
- : error;
57
-
58
- return {
59
- errorMessage,
60
- hasError: true,
61
- };
62
- }
63
-
64
- render() {
65
- const {children} = this.props;
66
- const {errorMessage, hasError} = this.state;
67
-
68
- if (hasError) {
69
- return (
70
- <div className={styles.Error}>
71
- <div className={styles.Message}>{errorMessage || 'Error'}</div>
72
- <Button className={styles.RetryButton} onClick={this._retry}>
73
- Dismiss
74
- </Button>
75
- </div>
76
- );
77
- }
78
-
79
- return children;
80
- }
81
-
82
- _retry = () => {
83
- const {dispatch} = this.props;
84
- dispatch({
85
- type: 'SELECT_ELEMENT_BY_ID',
86
- payload: null,
87
- });
88
- this.setState({
89
- errorMessage: null,
90
- hasError: false,
91
- });
92
- };
93
-}
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorBoundary.js
+15
-6
@@ -16,7 +16,8 @@ import SuspendingErrorView from './SuspendingErrorView';
16
17
type Props = {|
18
children: React$Node,
19
- store: Store,
19
+ canDismiss?: boolean,
20
+ store?: Store,
21
|};
22
23
type State = {|
@@ -70,18 +71,24 @@ export default class ErrorBoundary extends Component<Props, State> {
71
}
72
73
componentDidMount() {
73
- this.props.store.addListener('error', this._onStoreError);
74
+ const {store} = this.props;
75
+ if (store != null) {
76
+ store.addListener('error', this._onStoreError);
77
+ }
78
}
79
80
componentWillUnmount() {
77
- this.props.store.removeListener('error', this._onStoreError);
81
+ const {store} = this.props;
82
+ if (store != null) {
83
+ store.removeListener('error', this._onStoreError);
84
+ }
85
}
86
87
render() {
81
- const {children} = this.props;
88
+ const {canDismiss: canDismissProp, children} = this.props;
89
const {
90
callStack,
84
- canDismiss,
91
+ canDismiss: canDismissState,
92
componentStack,
93
errorMessage,
94
hasError,
@@ -92,7 +99,9 @@ export default class ErrorBoundary extends Component<Props, State> {
99
<ErrorView
100
callStack={callStack}
101
componentStack={componentStack}
95
- dismissError={canDismiss ? this._dismissError : null}
102
+ dismissError={
103
+ canDismissProp || canDismissState ? this._dismissError : null
104
+ }
105
errorMessage={errorMessage}>
106
<Suspense fallback={<SearchingGitHubIssues />}>
107
<SuspendingErrorView