-
Notifications
You must be signed in to change notification settings - Fork 47k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DevTools error boundary: Search for pre-existing GH issues
Previously the error boundary UI in DevTools showed a link to report the error on GitHub. This was helpful but resulted in a lot of duplicate issues. This commit adds an intermediate step of searching GitHub issues (using the public API) to find a pre-existing match and linking to it instead if one is found. Hopefully this will encourage people to add info to existing issues rather than report duplicates.
- Loading branch information
Brian Vaughn
committed
Apr 15, 2021
1 parent
96d00b9
commit b9b6de4
Showing
13 changed files
with
651 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
154 changes: 0 additions & 154 deletions
154
packages/react-devtools-shared/src/devtools/views/ErrorBoundary.js
This file was deleted.
Oops, something went wrong.
91 changes: 91 additions & 0 deletions
91
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorBoundary.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import * as React from 'react'; | ||
import {Component, Suspense} from 'react'; | ||
import ErrorView from './ErrorView'; | ||
import SearchingGitHubIssues from './SearchingGitHubIssues'; | ||
import SuspendingErrorView from './SuspendingErrorView'; | ||
|
||
type Props = {| | ||
children: React$Node, | ||
|}; | ||
|
||
type State = {| | ||
callStack: string | null, | ||
componentStack: string | null, | ||
errorMessage: string | null, | ||
hasError: boolean, | ||
|}; | ||
|
||
const InitialState: State = { | ||
callStack: null, | ||
componentStack: null, | ||
errorMessage: null, | ||
hasError: false, | ||
}; | ||
|
||
export default class ErrorBoundary 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, | ||
}; | ||
} | ||
|
||
componentDidCatch(error: any, {componentStack}: any) { | ||
const callStack = | ||
typeof error === 'object' && | ||
error !== null && | ||
error.hasOwnProperty('stack') | ||
? error.stack | ||
.split('\n') | ||
.slice(1) | ||
.join('\n') | ||
: null; | ||
|
||
this.setState({ | ||
callStack, | ||
componentStack, | ||
}); | ||
} | ||
|
||
render() { | ||
const {children} = this.props; | ||
const {callStack, componentStack, errorMessage, hasError} = this.state; | ||
|
||
if (hasError) { | ||
return ( | ||
<ErrorView | ||
callStack={callStack} | ||
componentStack={componentStack} | ||
errorMessage={errorMessage}> | ||
<Suspense fallback={<SearchingGitHubIssues />}> | ||
<SuspendingErrorView | ||
callStack={callStack} | ||
componentStack={componentStack} | ||
errorMessage={errorMessage} | ||
/> | ||
</Suspense> | ||
</ErrorView> | ||
); | ||
} | ||
|
||
return children; | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ErrorView.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import * as React from 'react'; | ||
import styles from './shared.css'; | ||
|
||
type Props = {| | ||
callStack: string | null, | ||
children: React$Node, | ||
componentStack: string | null, | ||
errorMessage: string | null, | ||
|}; | ||
|
||
export default function ErrorView({ | ||
callStack, | ||
children, | ||
componentStack, | ||
errorMessage, | ||
}: Props) { | ||
return ( | ||
<div className={styles.ErrorBoundary}> | ||
{children} | ||
<div className={styles.ErrorInfo}> | ||
<div className={styles.Header}> | ||
Uncaught Error: {errorMessage || ''} | ||
</div> | ||
{!!callStack && ( | ||
<div className={styles.Stack}> | ||
The error was thrown {callStack.trim()} | ||
</div> | ||
)} | ||
{!!componentStack && ( | ||
<div className={styles.Stack}> | ||
The error occurred {componentStack.trim()} | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
} |
68 changes: 68 additions & 0 deletions
68
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ReportNewIssue.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import * as React from 'react'; | ||
import Icon from '../Icon'; | ||
import styles from './shared.css'; | ||
|
||
type Props = {| | ||
callStack: string | null, | ||
componentStack: string | null, | ||
errorMessage: string | null, | ||
|}; | ||
|
||
export default function ReportNewIssue({ | ||
callStack, | ||
componentStack, | ||
errorMessage, | ||
}: Props) { | ||
let bugURL = process.env.GITHUB_URL; | ||
if (!bugURL) { | ||
return null; | ||
} | ||
|
||
const title = `Error: "${errorMessage || ''}"`; | ||
const label = 'Component: Developer Tools'; | ||
|
||
let body = 'Describe what you were doing when the bug occurred:'; | ||
body += '\n1. '; | ||
body += '\n2. '; | ||
body += '\n3. '; | ||
body += '\n\n---------------------------------------------'; | ||
body += '\nPlease do not remove the text below this line'; | ||
body += '\n---------------------------------------------'; | ||
body += `\n\nDevTools version: ${process.env.DEVTOOLS_VERSION || ''}`; | ||
if (callStack) { | ||
body += `\n\nCall stack: ${callStack.trim()}`; | ||
} | ||
if (componentStack) { | ||
body += `\n\nComponent stack: ${componentStack.trim()}`; | ||
} | ||
|
||
bugURL += `/issues/new?labels=${encodeURI(label)}&title=${encodeURI( | ||
title, | ||
)}&body=${encodeURI(body)}`; | ||
|
||
return ( | ||
<div className={styles.GitHubLinkRow}> | ||
<Icon className={styles.ReportIcon} type="bug" /> | ||
<a | ||
className={styles.ReportLink} | ||
href={bugURL} | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
title="Report bug"> | ||
Report this issue | ||
</a> | ||
<div className={styles.ReproSteps}> | ||
(Please include steps on how to reproduce it and the components used.) | ||
</div> | ||
</div> | ||
); | ||
} |
21 changes: 21 additions & 0 deletions
21
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/SearchingGitHubIssues.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import * as React from 'react'; | ||
import LoadingAnimation from 'react-devtools-shared/src/devtools/views/Components/LoadingAnimation'; | ||
import styles from './shared.css'; | ||
|
||
export default function SearchingGitHubIssues() { | ||
return ( | ||
<div className={styles.GitHubLinkRow}> | ||
<LoadingAnimation className={styles.LoadingIcon} /> | ||
Searching GitHub for reports of this error... | ||
</div> | ||
); | ||
} |
Oops, something went wrong.