WrappedRoute: allow navigating between pages to reset the ErrorBoundary
This commit is contained in:
parent
54aa09c6b1
commit
1a32dc178b
|
@ -1,6 +1,6 @@
|
||||||
import React, { ComponentProps, Suspense } from 'react';
|
import React, { Suspense, useEffect, useRef } from 'react';
|
||||||
import { ErrorBoundary } from 'react-error-boundary';
|
import { ErrorBoundary, type FallbackProps } from 'react-error-boundary';
|
||||||
import { Redirect, Route, useHistory, RouteProps, RouteComponentProps, match as MatchType } from 'react-router-dom';
|
import { Redirect, Route, useHistory, RouteProps, RouteComponentProps, match as MatchType, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import { Layout } from 'soapbox/components/ui';
|
import { Layout } from 'soapbox/components/ui';
|
||||||
import { useOwnAccount, useSettings } from 'soapbox/hooks';
|
import { useOwnAccount, useSettings } from 'soapbox/hooks';
|
||||||
|
@ -48,8 +48,8 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
const renderComponent = ({ match }: RouteComponentProps) => {
|
const renderComponent = ({ match }: RouteComponentProps) => {
|
||||||
if (Page) {
|
if (Page) {
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary FallbackComponent={renderError}>
|
<ErrorBoundary FallbackComponent={FallbackError}>
|
||||||
<Suspense fallback={renderLoading()}>
|
<Suspense fallback={<FallbackLoading />}>
|
||||||
<Page params={match.params} layout={layout} {...componentParams}>
|
<Page params={match.params} layout={layout} {...componentParams}>
|
||||||
<Component params={match.params} {...componentParams}>
|
<Component params={match.params} {...componentParams}>
|
||||||
{content}
|
{content}
|
||||||
|
@ -61,8 +61,8 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary FallbackComponent={renderError}>
|
<ErrorBoundary FallbackComponent={FallbackError}>
|
||||||
<Suspense fallback={renderLoading()}>
|
<Suspense fallback={<FallbackLoading />}>
|
||||||
<ColumnsArea layout={layout}>
|
<ColumnsArea layout={layout}>
|
||||||
<Component params={match.params} {...componentParams}>
|
<Component params={match.params} {...componentParams}>
|
||||||
{content}
|
{content}
|
||||||
|
@ -73,20 +73,6 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderWithLayout = (children: JSX.Element) => (
|
|
||||||
<>
|
|
||||||
<Layout.Main>
|
|
||||||
{children}
|
|
||||||
</Layout.Main>
|
|
||||||
|
|
||||||
<Layout.Aside />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderLoading = () => renderWithLayout(<ColumnLoading />);
|
|
||||||
const renderForbidden = () => renderWithLayout(<ColumnForbidden />);
|
|
||||||
const renderError = (props: ComponentProps<typeof ErrorColumn>) => renderWithLayout(<ErrorColumn {...props} />);
|
|
||||||
|
|
||||||
const loginRedirect = () => {
|
const loginRedirect = () => {
|
||||||
const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`);
|
const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`);
|
||||||
localStorage.setItem('soapbox:redirect_uri', actualUrl);
|
localStorage.setItem('soapbox:redirect_uri', actualUrl);
|
||||||
|
@ -104,13 +90,58 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
if (!account) {
|
if (!account) {
|
||||||
return loginRedirect();
|
return loginRedirect();
|
||||||
} else {
|
} else {
|
||||||
return renderForbidden();
|
return <FallbackForbidden />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Route {...rest} render={renderComponent} />;
|
return <Route {...rest} render={renderComponent} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface IFallbackLayout {
|
||||||
|
children: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FallbackLayout: React.FC<IFallbackLayout> = ({ children }) => (
|
||||||
|
<>
|
||||||
|
<Layout.Main>
|
||||||
|
{children}
|
||||||
|
</Layout.Main>
|
||||||
|
|
||||||
|
<Layout.Aside />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const FallbackLoading: React.FC = () => (
|
||||||
|
<FallbackLayout>
|
||||||
|
<ColumnLoading />
|
||||||
|
</FallbackLayout>
|
||||||
|
);
|
||||||
|
|
||||||
|
const FallbackForbidden: React.FC = () => (
|
||||||
|
<FallbackLayout>
|
||||||
|
<ColumnForbidden />
|
||||||
|
</FallbackLayout>
|
||||||
|
);
|
||||||
|
|
||||||
|
const FallbackError: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const firstUpdate = useRef(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (firstUpdate.current) {
|
||||||
|
firstUpdate.current = false;
|
||||||
|
} else {
|
||||||
|
resetErrorBoundary();
|
||||||
|
}
|
||||||
|
}, [location]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FallbackLayout>
|
||||||
|
<ErrorColumn error={error} onRetry={resetErrorBoundary} />
|
||||||
|
</FallbackLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
WrappedRoute,
|
WrappedRoute,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue