F: Implement ErrorFallback for root
This commit is contained in:
parent
532bf24df6
commit
d139c07b7a
|
@ -1,5 +1,4 @@
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
import { ErrorBoundary } from 'react-error-boundary';
|
|
||||||
import { Outlet } from 'react-router';
|
import { Outlet } from 'react-router';
|
||||||
|
|
||||||
import ConceptToaster from '@/app/ConceptToaster';
|
import ConceptToaster from '@/app/ConceptToaster';
|
||||||
|
@ -10,22 +9,10 @@ import ModalLoader from '@/components/ui/ModalLoader';
|
||||||
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
|
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
|
||||||
import { globals } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import ErrorFallback from './ErrorFallback';
|
|
||||||
import { GlobalDialogs } from './GlobalDialogs';
|
import { GlobalDialogs } from './GlobalDialogs';
|
||||||
import { GlobalTooltips } from './GlobalTooltips';
|
import { GlobalTooltips } from './GlobalTooltips';
|
||||||
import { NavigationState } from './Navigation/NavigationContext';
|
import { NavigationState } from './Navigation/NavigationContext';
|
||||||
|
|
||||||
const resetState = () => {
|
|
||||||
console.log('Resetting state after error fallback');
|
|
||||||
};
|
|
||||||
|
|
||||||
const logError = (error: Error, info: { componentStack?: string | null | undefined }) => {
|
|
||||||
console.log('Error fallback: ' + error.message);
|
|
||||||
if (info.componentStack) {
|
|
||||||
console.log('Component stack: ' + info.componentStack);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function ApplicationLayout() {
|
function ApplicationLayout() {
|
||||||
const mainHeight = useMainHeight();
|
const mainHeight = useMainHeight();
|
||||||
const viewportHeight = useViewportHeight();
|
const viewportHeight = useViewportHeight();
|
||||||
|
@ -35,41 +22,39 @@ function ApplicationLayout() {
|
||||||
const noFooter = useAppLayoutStore(state => state.noFooter);
|
const noFooter = useAppLayoutStore(state => state.noFooter);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary FallbackComponent={ErrorFallback} onError={logError} onReset={resetState}>
|
<NavigationState>
|
||||||
<NavigationState>
|
<div className='min-w-[20rem] antialiased h-full max-w-[120rem] mx-auto'>
|
||||||
<div className='min-w-[20rem] antialiased h-full max-w-[120rem] mx-auto'>
|
<ConceptToaster
|
||||||
<ConceptToaster
|
className='text-[14px] cc-animate-position'
|
||||||
className='text-[14px] cc-animate-position'
|
style={{ marginTop: noNavigationAnimation ? '1.5rem' : '3.5rem' }}
|
||||||
style={{ marginTop: noNavigationAnimation ? '1.5rem' : '3.5rem' }}
|
autoClose={3000}
|
||||||
autoClose={3000}
|
draggable={false}
|
||||||
draggable={false}
|
pauseOnFocusLoss={false}
|
||||||
pauseOnFocusLoss={false}
|
/>
|
||||||
/>
|
|
||||||
|
|
||||||
<Suspense fallback={<ModalLoader />}>
|
<Suspense fallback={<ModalLoader />}>
|
||||||
<GlobalDialogs />
|
<GlobalDialogs />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<GlobalTooltips />
|
<GlobalTooltips />
|
||||||
|
|
||||||
<Navigation />
|
<Navigation />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id={globals.main_scroll}
|
id={globals.main_scroll}
|
||||||
className='overflow-x-auto max-w-[100vw]'
|
className='overflow-x-auto max-w-[100vw]'
|
||||||
style={{
|
style={{
|
||||||
maxHeight: viewportHeight
|
maxHeight: viewportHeight
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<main className='cc-scroll-y' style={{ overflowY: showScroll ? 'scroll' : 'auto', minHeight: mainHeight }}>
|
<main className='cc-scroll-y' style={{ overflowY: showScroll ? 'scroll' : 'auto', minHeight: mainHeight }}>
|
||||||
<Suspense fallback={<Loader />}>
|
<Suspense fallback={<Loader />}>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</main>
|
</main>
|
||||||
{!noNavigation && !noFooter ? <Footer /> : null}
|
{!noNavigation && !noFooter ? <Footer /> : null}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</NavigationState>
|
</div>
|
||||||
</ErrorBoundary>
|
</NavigationState>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
import { type FallbackProps } from 'react-error-boundary';
|
import { useNavigate, useRouteError } from 'react-router';
|
||||||
|
|
||||||
import InfoError from '@/components/info/InfoError';
|
import InfoError from '@/components/info/InfoError';
|
||||||
import Button from '@/components/ui/Button';
|
import Button from '@/components/ui/Button';
|
||||||
|
|
||||||
function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
|
function ErrorFallback() {
|
||||||
|
const error = useRouteError();
|
||||||
|
const router = useNavigate();
|
||||||
|
|
||||||
|
function resetErrorBoundary() {
|
||||||
|
Promise.resolve(router('/')).catch(console.log);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col gap-3 my-3 items-center antialiased' role='alert'>
|
<div className='flex flex-col gap-3 my-3 items-center antialiased' role='alert'>
|
||||||
<h1 className='my-2'>Что-то пошло не так!</h1>
|
<h1 className='my-2'>Что-то пошло не так!</h1>
|
||||||
<Button onClick={resetErrorBoundary} text='Попробовать еще раз' />
|
<Button onClick={resetErrorBoundary} text='Вернуться на главную' />
|
||||||
<InfoError error={error as Error} />
|
<InfoError error={error as Error} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,13 +13,14 @@ import LoginPage from '@/pages/LoginPage';
|
||||||
import NotFoundPage from '@/pages/NotFoundPage';
|
import NotFoundPage from '@/pages/NotFoundPage';
|
||||||
|
|
||||||
import ApplicationLayout from './ApplicationLayout';
|
import ApplicationLayout from './ApplicationLayout';
|
||||||
|
import ErrorFallback from './ErrorFallback';
|
||||||
import { routes } from './urls';
|
import { routes } from './urls';
|
||||||
|
|
||||||
export const Router = createBrowserRouter([
|
export const Router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
element: <ApplicationLayout />,
|
element: <ApplicationLayout />,
|
||||||
errorElement: <NotFoundPage />,
|
errorElement: <ErrorFallback />,
|
||||||
loader: prefetchAuth,
|
loader: prefetchAuth,
|
||||||
hydrateFallbackElement: <Loader />,
|
hydrateFallbackElement: <Loader />,
|
||||||
children: [
|
children: [
|
||||||
|
|
Loading…
Reference in New Issue
Block a user