Improve AppError boundaries (#11107)
## What This PR aims to make sure all application exceptions are captured through react-error-boundaries Once merged we will have: - Root Level: AppErrorBoundary at the highest level (full screen) ==> this one needs to be working in any case, not relying on Theme, was not working - Route Level: AppErrorBoundary in DefaultLayout (full screen) ==> this was missing and it seems that error are not propagated outside of the router, making errors triggered in CommandMenu or NavigationDrawer missing - Page Level: AppErrorBoundary in DefaultLayout write around the Page itself (lower than CommandMenu + NavigationDrawer) - Manually triggered: example in ClientConfigProvider ## Screenshots App level (ex throw in IconsProvider) <img width="1512" alt="image" src="https://github.com/user-attachments/assets/18a14815-a203-4edf-b931-43068c3436ec" /> Route level (ex throw in CommandMenu) <img width="1512" alt="image" src="https://github.com/user-attachments/assets/ca066627-14c7-438e-a432-f0999a1f3b84" /> Page level (ex throw in RecordTable) <img width="1512" alt="image" src="https://github.com/user-attachments/assets/ffeaa935-02af-4762-8859-7a0ccf8b77e1" /> Manually Triggered (clientConfig, ex when backend is not up) <img width="1512" alt="image" src="https://github.com/user-attachments/assets/062d6d84-097a-4ed9-b6ce-763b8c27c659" />
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FallbackProps } from 'react-error-boundary';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
type AppErrorBoundaryEffectProps = Pick<FallbackProps, 'resetErrorBoundary'>;
|
||||
|
||||
export const AppErrorBoundaryEffect = ({
|
||||
resetErrorBoundary,
|
||||
}: AppErrorBoundaryEffectProps) => {
|
||||
const location = useLocation();
|
||||
|
||||
const [previousLocation] = useState(location);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDeeplyEqual(previousLocation, location)) {
|
||||
resetErrorBoundary();
|
||||
}
|
||||
}, [previousLocation, location, resetErrorBoundary]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { AppErrorDisplayProps } from '@/error-handler/types/AppErrorDisplayProps';
|
||||
import {
|
||||
AnimatedPlaceholder,
|
||||
AnimatedPlaceholderEmptyContainer,
|
||||
AnimatedPlaceholderEmptySubTitle,
|
||||
AnimatedPlaceholderEmptyTextContainer,
|
||||
AnimatedPlaceholderEmptyTitle,
|
||||
Button,
|
||||
IconRefresh,
|
||||
} from 'twenty-ui';
|
||||
|
||||
export const AppErrorDisplay = ({
|
||||
error,
|
||||
resetErrorBoundary,
|
||||
title = 'Sorry, something went wrong',
|
||||
}: AppErrorDisplayProps) => {
|
||||
return (
|
||||
<AnimatedPlaceholderEmptyContainer>
|
||||
<AnimatedPlaceholder type="errorIndex" />
|
||||
<AnimatedPlaceholderEmptyTextContainer>
|
||||
<AnimatedPlaceholderEmptyTitle>{title}</AnimatedPlaceholderEmptyTitle>
|
||||
<AnimatedPlaceholderEmptySubTitle>
|
||||
{error.message}
|
||||
</AnimatedPlaceholderEmptySubTitle>
|
||||
</AnimatedPlaceholderEmptyTextContainer>
|
||||
<Button
|
||||
Icon={IconRefresh}
|
||||
title="Reload"
|
||||
variant={'secondary'}
|
||||
onClick={resetErrorBoundary}
|
||||
/>
|
||||
</AnimatedPlaceholderEmptyContainer>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user