97 lines
2.3 KiB
TypeScript
97 lines
2.3 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import React, { Component, ErrorInfo, ReactNode } from "react";
|
||
|
|
import { Box, Button, Heading, Text, VStack } from "@chakra-ui/react";
|
||
|
|
|
||
|
|
interface Props {
|
||
|
|
children: ReactNode;
|
||
|
|
}
|
||
|
|
|
||
|
|
interface State {
|
||
|
|
hasError: boolean;
|
||
|
|
error: Error | null;
|
||
|
|
errorInfo: ErrorInfo | null;
|
||
|
|
}
|
||
|
|
|
||
|
|
class ErrorBoundary extends Component<Props, State> {
|
||
|
|
constructor(props: Props) {
|
||
|
|
super(props);
|
||
|
|
this.state = {
|
||
|
|
hasError: false,
|
||
|
|
error: null,
|
||
|
|
errorInfo: null,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
static getDerivedStateFromError(error: Error): State {
|
||
|
|
return {
|
||
|
|
hasError: true,
|
||
|
|
error,
|
||
|
|
errorInfo: null,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||
|
|
// Log error to error tracking service
|
||
|
|
console.error("Error caught by boundary:", error, errorInfo);
|
||
|
|
|
||
|
|
this.setState({
|
||
|
|
error,
|
||
|
|
errorInfo,
|
||
|
|
});
|
||
|
|
|
||
|
|
// In production, send to error tracking service
|
||
|
|
if (process.env.NODE_ENV === "production") {
|
||
|
|
// Example: sendToErrorTracking(error, errorInfo);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
handleReset = () => {
|
||
|
|
this.setState({
|
||
|
|
hasError: false,
|
||
|
|
error: null,
|
||
|
|
errorInfo: null,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
render() {
|
||
|
|
if (this.state.hasError) {
|
||
|
|
return (
|
||
|
|
<Box p={8} textAlign="center">
|
||
|
|
<VStack spacing={4}>
|
||
|
|
<Heading size="lg" color="red.400">
|
||
|
|
Something went wrong
|
||
|
|
</Heading>
|
||
|
|
<Text color="gray.400">
|
||
|
|
{this.state.error?.message || "An unexpected error occurred"}
|
||
|
|
</Text>
|
||
|
|
{process.env.NODE_ENV === "development" && this.state.errorInfo && (
|
||
|
|
<Box
|
||
|
|
p={4}
|
||
|
|
bg="gray.800"
|
||
|
|
borderRadius="md"
|
||
|
|
maxW="4xl"
|
||
|
|
overflow="auto"
|
||
|
|
textAlign="left"
|
||
|
|
>
|
||
|
|
<Text fontSize="sm" fontFamily="mono" whiteSpace="pre-wrap">
|
||
|
|
{this.state.error?.stack}
|
||
|
|
{"\n\n"}
|
||
|
|
{this.state.errorInfo.componentStack}
|
||
|
|
</Text>
|
||
|
|
</Box>
|
||
|
|
)}
|
||
|
|
<Button onClick={this.handleReset} colorScheme="blue">
|
||
|
|
Try Again
|
||
|
|
</Button>
|
||
|
|
</VStack>
|
||
|
|
</Box>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return this.props.children;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export default ErrorBoundary;
|