From 02924c24d5d022efcc7544efec3d75b99a529238 Mon Sep 17 00:00:00 2001 From: Paden Clayton Date: Thu, 23 Jul 2020 10:21:39 -0500 Subject: [PATCH 01/24] refactor: add configurable error boundary around App component contents. --- packages/docusaurus/src/client/App.tsx | 18 ++-- .../docusaurus/src/client/ErrorBoundary.tsx | 82 +++++++++++++++++++ 2 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 packages/docusaurus/src/client/ErrorBoundary.tsx diff --git a/packages/docusaurus/src/client/App.tsx b/packages/docusaurus/src/client/App.tsx index d7d4cd4eb78e..a10693f37703 100644 --- a/packages/docusaurus/src/client/App.tsx +++ b/packages/docusaurus/src/client/App.tsx @@ -13,6 +13,7 @@ import globalData from '@generated/globalData'; import siteMetadata from '@generated/site-metadata'; import renderRoutes from './exports/renderRoutes'; import DocusaurusContext from './exports/context'; +import ErrorBoundary from './ErrorBoundary'; import PendingNavigation from './PendingNavigation'; import './client-lifecycles-dispatcher'; @@ -24,13 +25,18 @@ function App(): JSX.Element { setIsClient(true); }, []); + const logError = process.env.NODE_ENV !== 'production'; + const showError = process.env.NODE_ENV !== 'production'; + return ( - - - {renderRoutes(routes)} - - + + + + {renderRoutes(routes)} + + + ); } diff --git a/packages/docusaurus/src/client/ErrorBoundary.tsx b/packages/docusaurus/src/client/ErrorBoundary.tsx new file mode 100644 index 000000000000..d08a73b6ee5c --- /dev/null +++ b/packages/docusaurus/src/client/ErrorBoundary.tsx @@ -0,0 +1,82 @@ +/** + * 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. + */ + +import React from 'react'; +import {withRouter} from 'react-router-dom'; +import siteConfig from '@generated/docusaurus.config'; + +interface Props { + logError: boolean; + showError: boolean; +} + +interface State { + error: Error; + errorInfo: React.ErrorInfo; +} + +class ErrorBoundary extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + error: null, + errorInfo: null, + }; + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { + const {logError = false} = this.props; + const { + errorBoundary: { + consoleHeading = 'An error occurred, here are the details.', + }, + } = siteConfig; + + // Catch errors in any components below and re-render with error message + this.setState({ + error, + errorInfo, + }); + + // Log our errors to the console as well + if (logError) { + console.error(consoleHeading, error, errorInfo); + } + } + + render() { + const {children, showError = false} = this.props; + const {error, errorInfo} = this.state; + const { + errorBoundary: { + heading = 'An error occurred, please contact the development team.', + }, + } = siteConfig; + + if (errorInfo) { + // Let's output our error + return ( +
+

{heading}

+ {showError && ( +
+ {error && error.toString()} +
+ {errorInfo.componentStack} +
+ )} +
+ ); + } + + // Normally, just render children + return children; + } +} + +export default withRouter(ErrorBoundary); From ce5c310ff7f014dfd492ee27ef1ce33d193052b0 Mon Sep 17 00:00:00 2001 From: Paden Clayton Date: Thu, 23 Jul 2020 10:38:04 -0500 Subject: [PATCH 02/24] fix state types and defaults for ErrorBoundary. --- packages/docusaurus/src/client/ErrorBoundary.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/docusaurus/src/client/ErrorBoundary.tsx b/packages/docusaurus/src/client/ErrorBoundary.tsx index d08a73b6ee5c..2565e927cb7b 100644 --- a/packages/docusaurus/src/client/ErrorBoundary.tsx +++ b/packages/docusaurus/src/client/ErrorBoundary.tsx @@ -15,8 +15,8 @@ interface Props { } interface State { - error: Error; - errorInfo: React.ErrorInfo; + error: Error | null; + errorInfo: React.ErrorInfo | null; } class ErrorBoundary extends React.Component { @@ -34,7 +34,7 @@ class ErrorBoundary extends React.Component { const { errorBoundary: { consoleHeading = 'An error occurred, here are the details.', - }, + } = {}, } = siteConfig; // Catch errors in any components below and re-render with error message @@ -55,7 +55,7 @@ class ErrorBoundary extends React.Component { const { errorBoundary: { heading = 'An error occurred, please contact the development team.', - }, + } = {}, } = siteConfig; if (errorInfo) { From a125c60649652270f329f9cb6b8860aff87ad918 Mon Sep 17 00:00:00 2001 From: Paden Clayton Date: Fri, 24 Jul 2020 15:25:52 -0500 Subject: [PATCH 03/24] App level error boundary now only shows errors when canUseDOM is enabled. --- packages/docusaurus/src/client/ErrorBoundary.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/docusaurus/src/client/ErrorBoundary.tsx b/packages/docusaurus/src/client/ErrorBoundary.tsx index 2565e927cb7b..f84d049a3503 100644 --- a/packages/docusaurus/src/client/ErrorBoundary.tsx +++ b/packages/docusaurus/src/client/ErrorBoundary.tsx @@ -7,6 +7,7 @@ import React from 'react'; import {withRouter} from 'react-router-dom'; +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; import siteConfig from '@generated/docusaurus.config'; interface Props { @@ -38,10 +39,12 @@ class ErrorBoundary extends React.Component { } = siteConfig; // Catch errors in any components below and re-render with error message - this.setState({ - error, - errorInfo, - }); + if (ExecutionEnvironment.canUseDOM) { + this.setState({ + error, + errorInfo, + }); + } // Log our errors to the console as well if (logError) { From d788e604a259185a8510c094ee03f40c44ba67a2 Mon Sep 17 00:00:00 2001 From: Paden Clayton Date: Fri, 24 Jul 2020 15:29:08 -0500 Subject: [PATCH 04/24] Wrapped Layout children with new global error boundary with fallback theme implementation. --- .../src/theme/Layout/index.tsx | 5 +- .../exports/DocusaurusErrorBoundary.tsx | 64 +++++++++++++++++++ .../src/client/theme-fallback/Error/index.js | 24 +++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 packages/docusaurus/src/client/exports/DocusaurusErrorBoundary.tsx create mode 100644 packages/docusaurus/src/client/theme-fallback/Error/index.js diff --git a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx index d36de4c0832e..9b0ed3924f87 100644 --- a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx @@ -9,6 +9,7 @@ import React, {ReactNode} from 'react'; import Head from '@docusaurus/Head'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useBaseUrl from '@docusaurus/useBaseUrl'; +import DocusaurusErrorBoundary from '@docusaurus/DocusaurusErrorBoundary'; import ThemeProvider from '@theme/ThemeProvider'; import UserPreferencesProvider from '@theme/UserPreferencesProvider'; @@ -88,7 +89,9 @@ function Layout(props: Props): JSX.Element { -
{children}
+
+ {children} +
{!noFooter &&