@samitouri / QOS-React-2 / commits / 7bef382bf9

Errors thrown by Store can be dismissed in boundary (#21520)

Brian Vaughn committed May 18, 2021 at 07:36 UTC 7bef382bf92e380f2b94e825cf35b8af58f8a2ec
3 files changed +55 -5
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorBoundary.js
+18 -2
@@ -21,6 +21,7 @@ type Props = {|
21
22 type State = {|
23 callStack: string | null,
24 + canDismiss: boolean,
25 componentStack: string | null,
26 errorMessage: string | null,
27 hasError: boolean,
@@ -28,6 +29,7 @@ type State = {|
29
30 const InitialState: State = {
31 callStack: null,
32 + canDismiss: false,
33 componentStack: null,
34 errorMessage: null,
35 hasError: false,
@@ -77,13 +79,20 @@ export default class ErrorBoundary extends Component<Props, State> {
79
80 render() {
81 const {children} = this.props;
80 - const {callStack, componentStack, errorMessage, hasError} = this.state;
82 + const {
83 + callStack,
84 + canDismiss,
85 + componentStack,
86 + errorMessage,
87 + hasError,
88 + } = this.state;
89
90 if (hasError) {
91 return (
92 <ErrorView
93 callStack={callStack}
94 componentStack={componentStack}
95 + dismissError={canDismiss ? this._dismissError : null}
96 errorMessage={errorMessage}>
97 <Suspense fallback={<SearchingGitHubIssues />}>
98 <SuspendingErrorView
@@ -99,9 +108,16 @@ export default class ErrorBoundary extends Component<Props, State> {
108 return children;
109 }
110
111 + _dismissError = () => {
112 + this.setState(InitialState);
113 + };
114 +
115 _onStoreError = (error: Error) => {
116 if (!this.state.hasError) {
104 - this.setState(ErrorBoundary.getDerivedStateFromError(error));
117 + this.setState({
118 + ...ErrorBoundary.getDerivedStateFromError(error),
119 + canDismiss: true,
120 + });
121 }
122 };
123 }
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorView.js
+14 -2
@@ -8,12 +8,15 @@
8 */
9
10 import * as React from 'react';
11 +import Button from '../Button';
12 +import ButtonIcon from '../ButtonIcon';
13 import styles from './shared.css';
14
15 type Props = {|
16 callStack: string | null,
17 children: React$Node,
18 componentStack: string | null,
19 + dismissError: Function | null,
20 errorMessage: string | null,
21 |};
22
@@ -21,14 +24,23 @@ export default function ErrorView({
24 callStack,
25 children,
26 componentStack,
27 + dismissError = null,
28 errorMessage,
29 }: Props) {
30 return (
31 <div className={styles.ErrorBoundary}>
32 {children}
33 <div className={styles.ErrorInfo}>
30 - <div className={styles.Header}>
31 - Uncaught Error: {errorMessage || ''}
34 + <div className={styles.HeaderRow}>
35 + <div className={styles.Header}>
36 + Uncaught Error: {errorMessage || ''}
37 + </div>
38 + {dismissError !== null && (
39 + <Button className={styles.CloseButton} onClick={dismissError}>
40 + Dismiss
41 + <ButtonIcon className={styles.CloseButtonIcon} type="close" />
42 + </Button>
43 + )}
44 </div>
45 {!!callStack && (
46 <div className={styles.Stack}>
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/shared.css
+23 -1
@@ -37,12 +37,22 @@
37 overflow: auto;
38 }
39
40 -.Header {
40 +.HeaderRow {
41 + display: flex;
42 + flex-direction: row;
43 font-size: var(--font-size-sans-large);
44 font-weight: bold;
45 color: var(--color-error-text);
46 }
47
48 +.Header {
49 + flex: 1 1 auto;
50 + overflow: hidden;
51 + text-overflow: ellipsis;
52 + white-space: nowrap;
53 + min-width: 0;
54 +}
55 +
56 .Stack {
57 margin-top: 0.5rem;
58 white-space: pre-wrap;
@@ -75,9 +85,21 @@
85 .ReproSteps {
86 margin-left: 0.25rem;
87 color: var(--color-console-warning-text);
88 + overflow: hidden;
89 + text-overflow: ellipsis;
90 + white-space: nowrap;
91 + min-width: 0;
92 }
93
94 .UpdateExistingIssuePrompt {
95 margin-right: 0.25rem;
96 color: var(--color-console-warning-text);
97 +}
98 +
99 +.CloseButton {
100 + font-weight: bold;
101 +}
102 +
103 +.CloseButtonIcon {
104 + margin-left: 0.25rem;
105 }
\ No newline at end of file