mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-04 13:26:00 -04:00
[ENG-1366] Improve ErrorBoundary so user can't get stuck on it (#1701)
improve error boundary
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { captureException } from '@sentry/browser';
|
||||
import { FallbackProps } from 'react-error-boundary';
|
||||
import { useRouteError } from 'react-router';
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
ErrorBoundary,
|
||||
ErrorBoundaryPropsWithComponent,
|
||||
FallbackProps
|
||||
} from 'react-error-boundary';
|
||||
import { Navigate, useRouteError } from 'react-router';
|
||||
import { useDebugState } from '@sd/client';
|
||||
import { Button, Dialogs } from '@sd/ui';
|
||||
|
||||
@@ -8,18 +13,24 @@ import { showAlertDialog } from './components';
|
||||
import { useOperatingSystem, useTheme } from './hooks';
|
||||
import { usePlatform } from './util/Platform';
|
||||
|
||||
const RENDERING_ERROR_LOCAL_STORAGE_KEY = 'was-rendering-error';
|
||||
|
||||
export function RouterErrorBoundary() {
|
||||
const error = useRouteError();
|
||||
|
||||
const reloadBtn = () => {
|
||||
location.reload();
|
||||
localStorage.setItem(RENDERING_ERROR_LOCAL_STORAGE_KEY, 'true');
|
||||
};
|
||||
|
||||
return (
|
||||
<ErrorPage
|
||||
message={(error as any).toString()}
|
||||
sendReportBtn={() => {
|
||||
captureException(error);
|
||||
location.reload();
|
||||
}}
|
||||
reloadBtn={() => {
|
||||
location.reload();
|
||||
reloadBtn();
|
||||
}}
|
||||
reloadBtn={reloadBtn}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -59,6 +70,23 @@ export function ErrorPage({
|
||||
const os = useOperatingSystem();
|
||||
const platform = usePlatform();
|
||||
const isMacOS = os === 'macOS';
|
||||
const [redirecting, _] = useState(() =>
|
||||
localStorage.getItem(RENDERING_ERROR_LOCAL_STORAGE_KEY)
|
||||
);
|
||||
|
||||
// If the user is on a page and the user presses "Reset" on the error boundary, it may crash in rendering causing the user to get stuck on the error page.
|
||||
// If it crashes again, we redirect them instead of infinitely crashing.
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem(RENDERING_ERROR_LOCAL_STORAGE_KEY) !== null) {
|
||||
localStorage.removeItem(RENDERING_ERROR_LOCAL_STORAGE_KEY);
|
||||
window.location.pathname = '/';
|
||||
console.error(
|
||||
'Hit error boundary after reloading. Redirecting to overview screen!',
|
||||
redirecting
|
||||
);
|
||||
}
|
||||
});
|
||||
if (redirecting) return null; // To stop flash of error boundary after `localStorage` is reset in the first render and the check above starts being `false`
|
||||
|
||||
const resetHandler = () => {
|
||||
showAlertDialog({
|
||||
@@ -137,3 +165,24 @@ export function ErrorPage({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const BetterErrorBoundary = ({
|
||||
children,
|
||||
FallbackComponent,
|
||||
...props
|
||||
}: ErrorBoundaryPropsWithComponent) => {
|
||||
useEffect(() => {
|
||||
const id = setTimeout(
|
||||
() => localStorage.removeItem(RENDERING_ERROR_LOCAL_STORAGE_KEY),
|
||||
1000
|
||||
);
|
||||
|
||||
return () => clearTimeout(id);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ErrorBoundary FallbackComponent={FallbackComponent} {...props}>
|
||||
{children}
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,6 @@ import dayjs from 'dayjs';
|
||||
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { RouterProvider, RouterProviderProps } from 'react-router-dom';
|
||||
import {
|
||||
NotificationContextProvider,
|
||||
@@ -20,7 +19,7 @@ import { TooltipProvider } from '@sd/ui';
|
||||
|
||||
import { P2P } from './app/p2p';
|
||||
import { WithPrismTheme } from './components/TextViewer/prism';
|
||||
import ErrorFallback from './ErrorFallback';
|
||||
import ErrorFallback, { BetterErrorBoundary } from './ErrorFallback';
|
||||
|
||||
export { ErrorPage } from './ErrorFallback';
|
||||
export * from './app';
|
||||
@@ -59,7 +58,7 @@ export const SpacedriveInterface = (props: { router: RouterProviderProps['router
|
||||
useLoadBackendFeatureFlags();
|
||||
|
||||
return (
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<BetterErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<TooltipProvider>
|
||||
<P2PContextProvider>
|
||||
<NotificationContextProvider>
|
||||
@@ -70,6 +69,6 @@ export const SpacedriveInterface = (props: { router: RouterProviderProps['router
|
||||
</NotificationContextProvider>
|
||||
</P2PContextProvider>
|
||||
</TooltipProvider>
|
||||
</ErrorBoundary>
|
||||
</BetterErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user