diff --git a/package-lock.json b/package-lock.json
index 6a366d6c61a1..68ea17fc20b8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -69,6 +69,7 @@
"react-collapse": "^5.1.0",
"react-content-loader": "^6.1.0",
"react-dom": "18.1.0",
+ "react-error-boundary": "^4.0.11",
"react-map-gl": "^7.1.3",
"react-native": "0.72.3",
"react-native-blob-util": "^0.17.3",
@@ -40187,6 +40188,17 @@
"react": "^18.1.0"
}
},
+ "node_modules/react-error-boundary": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.11.tgz",
+ "integrity": "sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "peerDependencies": {
+ "react": ">=16.13.1"
+ }
+ },
"node_modules/react-freeze": {
"version": "1.0.3",
"license": "MIT",
@@ -75742,6 +75754,14 @@
"scheduler": "^0.22.0"
}
},
+ "react-error-boundary": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.11.tgz",
+ "integrity": "sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==",
+ "requires": {
+ "@babel/runtime": "^7.12.5"
+ }
+ },
"react-freeze": {
"version": "1.0.3",
"requires": {}
diff --git a/package.json b/package.json
index 0605d44d89fc..72574455719b 100644
--- a/package.json
+++ b/package.json
@@ -112,6 +112,7 @@
"react-content-loader": "^6.1.0",
"react-dom": "18.1.0",
"react-map-gl": "^7.1.3",
+ "react-error-boundary": "^4.0.11",
"react-native": "0.72.3",
"react-native-blob-util": "^0.17.3",
"react-native-collapsible": "^1.6.0",
diff --git a/src/components/ErrorBoundary/BaseErrorBoundary.js b/src/components/ErrorBoundary/BaseErrorBoundary.js
index e479b04f7ade..d626442e81dd 100644
--- a/src/components/ErrorBoundary/BaseErrorBoundary.js
+++ b/src/components/ErrorBoundary/BaseErrorBoundary.js
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
+import {ErrorBoundary} from 'react-error-boundary';
import BootSplash from '../../libs/BootSplash';
import GenericErrorPage from '../../pages/ErrorPage/GenericErrorPage';
@@ -22,40 +23,27 @@ const defaultProps = {
* This component captures an error in the child component tree and logs it to the server
* It can be used to wrap the entire app as well as to wrap specific parts for more granularity
* @see {@link https://reactjs.org/docs/error-boundaries.html#where-to-place-error-boundaries}
+ * @return {React.Component}
*/
-class BaseErrorBoundary extends React.Component {
- constructor(props) {
- super(props);
- this.state = {hasError: false};
- this.clearError = this.clearError.bind(this);
- }
-
- static getDerivedStateFromError() {
- // Update state so the next render will show the fallback UI.
- return {hasError: true};
- }
-
- componentDidCatch(error, errorInfo) {
- this.props.logError(this.props.errorMessage, error, JSON.stringify(errorInfo));
-
+function BaseErrorBoundary({logError, errorMessage, children}) {
+ const catchError = (error, errorInfo) => {
+ logError(errorMessage, error, JSON.stringify(errorInfo));
// We hide the splash screen since the error might happened during app init
BootSplash.hide();
- }
-
- clearError() {
- this.setState({hasError: false});
- }
-
- render() {
- if (this.state.hasError) {
- return ;
- }
-
- return this.props.children;
- }
+ };
+
+ return (
+ }
+ onError={catchError}
+ >
+ {children}
+
+ );
}
BaseErrorBoundary.propTypes = propTypes;
BaseErrorBoundary.defaultProps = defaultProps;
+BaseErrorBoundary.displayName = 'BaseErrorBoundary';
export default BaseErrorBoundary;
diff --git a/src/pages/ErrorPage/GenericErrorPage.js b/src/pages/ErrorPage/GenericErrorPage.js
index 3ff3bc686419..02ab38a1ef20 100644
--- a/src/pages/ErrorPage/GenericErrorPage.js
+++ b/src/pages/ErrorPage/GenericErrorPage.js
@@ -1,6 +1,6 @@
import React from 'react';
-import PropTypes from 'prop-types';
import {View} from 'react-native';
+import {useErrorBoundary} from 'react-error-boundary';
import Icon from '../../components/Icon';
import defaultTheme from '../../styles/themes/default';
import * as Expensicons from '../../components/Icon/Expensicons';
@@ -19,12 +19,11 @@ import * as StyleUtils from '../../styles/StyleUtils';
const propTypes = {
...withLocalizePropTypes,
-
- /** Callback to call on refresh button click */
- onRefresh: PropTypes.func.isRequired,
};
-function GenericErrorPage(props) {
+function GenericErrorPage({translate}) {
+ const {resetBoundary} = useErrorBoundary();
+
return (
{({paddingBottom}) => (
@@ -40,12 +39,12 @@ function GenericErrorPage(props) {
/>
- {props.translate('genericErrorPage.title')}
+ {translate('genericErrorPage.title')}
- {`${props.translate('genericErrorPage.body.helpTextConcierge')} `}
+ {`${translate('genericErrorPage.body.helpTextConcierge')} `}