Skip to content

Commit

Permalink
feat: add ErrorBoundary
Browse files Browse the repository at this point in the history
  • Loading branch information
exKAZUu committed Sep 24, 2024
1 parent b27f5fb commit cb83e24
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/app/(withAuth)/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const SettingsPage: NextPage = async () => {
<form action={updateDisplayName}>
<VStack align="stretch" spacing={4}>
<FormControl>
<FormLabel>あなたの表示名</FormLabel>
<FormLabel>あなたの表示名(現在は未使用のため、設定する必要はありません。)</FormLabel>
<Input bg="white" defaultValue={user?.displayName} maxW="sm" name="displayName" type="text" />
</FormControl>

Expand Down
97 changes: 97 additions & 0 deletions src/components/organisms/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import type { ErrorInfo } from 'react';
import type React from 'react';
import { Component } from 'react';
import { MdContentCopy } from 'react-icons/md';

import { logger } from '../../infrastructures/pino';
import { Box, Button, Code, Heading, Text, VStack, useToast } from '../../infrastructures/useClient/chakra';

type Props = {
children: React.ReactNode;
};

type State = {
hasError: boolean;
error?: Error;
errorInfo?: ErrorInfo;
};

export class ErrorBoundary extends Component<Props, State> {
static getDerivedStateFromError(error: Error): State {
logger.error('getDerivedStateFromError:', error);
return { hasError: true, error };
}
constructor(props: Props) {
super(props);

this.state = { hasError: false };
}

componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
logger.error('componentDidCatch:', { error, errorInfo });
this.setState({ hasError: true, error, errorInfo });
}
render(): React.ReactNode {
if (this.state.hasError) {
const errorText = `Error:
- Name: ${this.state.error?.name}
- Message: ${this.state.error?.message}
- Stack: ----------- start -----------
${this.state.error?.stack}
---------------- end -----------------
Error Info:
- Componet Stack: ----------- start -----------
${this.state.errorInfo?.componentStack}
-------------------- end ----------------------`;

return <ErrorBoundaryContent errorText={errorText} onReset={() => this.setState({ hasError: false })} />;
}

return this.props.children;
}
}

const ErrorBoundaryContent: React.FC<{ errorText: string; onReset: () => void }> = ({ errorText, onReset }) => {
const toast = useToast();

return (
<Box borderRadius="lg" borderWidth={1} boxShadow="md" p={4}>
<VStack align="stretch" spacing={4}>
<Heading as="h2" color="red.500" size="xl">
エラーが発生しました
</Heading>
<Text>
予期せぬエラーが発生しました。問題が解決しない場合は、以下のエラー全文を坂本
([email protected]) にお知らせください。
</Text>
<Button colorScheme="blue" onClick={onReset}>
再試行
</Button>
<Box bg="gray.100" borderRadius="md" p={3} position="relative">
<Button
leftIcon={<MdContentCopy />}
position="absolute"
right={2}
size="sm"
top={2}
onClick={() => {
navigator.clipboard.writeText(errorText);
toast({
title: 'コピーしました',
status: 'success',
duration: 2000,
isClosable: true,
});
}}
>
コピー
</Button>
<Code display="block" fontFamily="monospace" overflowX="auto" whiteSpace="pre-wrap">
{errorText}
</Code>
</Box>
</VStack>
</Box>
);
};
29 changes: 16 additions & 13 deletions src/components/organisms/Providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { backendTrpcReact, backendTrpcReactClient } from '../../infrastructures/
import { ChakraProvider, useTheme } from '../../infrastructures/useClient/chakra';
import { theme } from '../../theme';

import { ErrorBoundary } from './ErrorBoundary';

ensureSuperTokensReactInit();

const queryClient = new QueryClient();
Expand All @@ -20,19 +22,20 @@ export const Providers: React.FC<{ children: React.ReactNode }> = ({ children })
setRouter(useRouter(), usePathname() || window.location.pathname);

return (
<SuperTokensWrapper>
<backendTrpcReact.Provider client={backendTrpcReactClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
{/* Chakra UI */}
<CacheProvider>
<ChakraProvider theme={theme}>
<PageTransitionProgressBar />
{children}
</ChakraProvider>
</CacheProvider>
</QueryClientProvider>
</backendTrpcReact.Provider>
</SuperTokensWrapper>
<CacheProvider>
<ChakraProvider theme={theme}>
<ErrorBoundary>
<SuperTokensWrapper>
<backendTrpcReact.Provider client={backendTrpcReactClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<PageTransitionProgressBar />
{children}
</QueryClientProvider>
</backendTrpcReact.Provider>
</SuperTokensWrapper>
</ErrorBoundary>
</ChakraProvider>
</CacheProvider>
);
};

Expand Down

0 comments on commit cb83e24

Please sign in to comment.